วิธีรับ CRON เพื่อโทรใน PATH ที่ถูกต้อง


125

ฉันพยายามให้ cron เรียกใน PATH ที่ถูกต้อง เมื่อฉันเรียกใช้สคริปต์ Python จากเชลล์สคริปต์จะทำงานได้ดีเนื่องจากใช้ PATH ที่ตั้งค่าใน bashrc แต่เมื่อฉันใช้ cron PATH ทั้งหมดจะไม่ใช้จาก bashrc มีไฟล์ที่ฉันสามารถป้อน PATH ลงใน cron เช่น bashrc หรือวิธีเรียก PATH จาก bashrc ได้หรือไม่

ขออภัยฉันคิดว่าฉันพูดไม่ถูกต้องฉันสามารถเรียกใช้สคริปต์ที่ถูกต้องได้ (หมายถึงเส้นทางไปยังสคริปต์ใน crontab ไม่ใช่ปัญหาที่นี่) เมื่อสคริปต์นั้นกำลังทำงานอยู่ฉันจะรันบิลด์และสิ่งนี้ใช้ ตั้งค่าเส้นทางใน.bashrc. เมื่อฉันเรียกใช้สคริปต์เมื่อฉันเข้าสู่ระบบ.bashrcPATHs จะถูกดึงเข้ามาเนื่องจาก cron ไม่ทำงานในเชลล์ต่อการบอกว่ามันไม่ดึงเข้า.bashrcมา มีวิธีดึงสิ่งนี้โดยไม่ต้องเขียน bash script wrapper หรือไม่?


นอกจากนี้ยังดูคำแนะนำที่ให้ไว้ที่นี่สำหรับวิธีการตั้งค่า bashrc เพื่อทำงานกับ cronjobs: stackoverflow.com/q/15557777/1025391
moooeeeep

2
คำสั่งวิเศษง่ายและถูกต้องเพื่อให้โปรไฟล์ของคุณรวมอยู่ในสภาพแวดล้อมปัจจุบันคือsource /etc/profileมันควรกิน.bashrcและสิ่งอื่น ๆ ที่อาจขาดหายไปสำหรับคุณ การจัดหาโปรไฟล์ที่ชัดเจนจะมีประโยชน์มากหากคุณต้องการให้สคริปต์บางสคริปต์ทำงาน "แบบสแตนด์อโลน" นอกจากนี้ยังป้องกันจากสภาพแวดล้อมที่แปลกประหลาดและอื่น ๆ ...
exa

1
@exa +100 ทำให้shสคริปต์ที่เรียกโดย crontab ทำงาน คุณสามารถยืนยันได้ว่าจะอัปเดตเส้นทางโดยเพิ่มงานที่ชอบ* * * * * echo $PATH > ~/crontab_path.txtและตรวจสอบไฟล์หลังจากนั้นหนึ่งนาที
geotheory

คำตอบ:


177

ฉันใช้/etc/crontab. ฉันใช้viและป้อน PATHs ที่ฉันต้องการในไฟล์นี้และเรียกใช้ในฐานะรูท crontab ปกติจะเขียนทับ PATH ที่คุณตั้งค่าไว้ ดีสอนเกี่ยวกับวิธีการทำเช่นนี้

ไฟล์ cron ทั้งระบบมีลักษณะดังนี้:

This has the username field, as used by /etc/crontab.
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file.
# This file also has a username field, that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user   command
42 6 * * *   root    run-parts --report /etc/cron.daily
47 6 * * 7   root    run-parts --report /etc/cron.weekly
52 6 1 * *   root    run-parts --report /etc/cron.monthly
01 01 * * 1-5 root python /path/to/file.py

17
วิธีนี้ใช้ได้กับ crontab -e ในระดับผู้ใช้และปลอดภัยกว่าด้วย
Robert Brisita

2
ฉันสามารถใช้ bash แทน sh ได้หรือไม่?
qed

1
เป็นเรื่องแปลก (สำหรับฉัน) ที่ PATH เริ่มต้นตั้งค่าใน / etc / crontab ดังที่แสดงโดย @chrissygormley และตั้งค่าใน crontab (Ubuntu) ของฉันแตกต่างจากพา ธ ใน / etc / environment โดยเฉพาะทำให้ / sbin และ / bin ข้างหน้า / usr / sbin และ / usr / bin ตอนนี้ฉันได้เปลี่ยนสิ่งนี้ใน / etc / crontab ของฉันเพื่อให้เหมือนกับสภาพแวดล้อมของผู้ใช้
scoobydoo

ไม่ได้ผลสำหรับฉัน. ฉันกำลังส่งออกเนื้อหา cron ไปยังไฟล์ Cron ทำงานสร้างไฟล์ แต่ไม่ได้ใส่เนื้อหาใด ๆ ลงไป
Volatil3

2
ดูเหมือนว่าเส้นทางทั้งหมดที่ตั้งไว้/etc/crontabจะไม่พร้อมใช้งานสำหรับ cron เมื่อรันเป็นรูทใน Ubuntu 14.04 ( sudo crontab -e)
David Oliver

50

เป็นไปได้มากว่า cron กำลังทำงานในสภาพแวดล้อมที่เบาบางมาก ตรวจสอบตัวแปรสภาพแวดล้อมที่ cron ใช้โดยการต่อท้ายงานดัมมี่ซึ่งถ่ายโอนข้อมูลenvไปยังไฟล์ดังนี้:

* * * * * env > env_dump.txt

เปรียบเทียบกับผลลัพธ์ของenvในเซสชันเชลล์ปกติ

คุณสามารถเพิ่มตัวแปรสภาพแวดล้อมของคุณเองลงใน crontab ในเครื่องได้โดยกำหนดไว้ที่ด้านบนสุดของ crontab

นี่คือการแก้ไขอย่างรวดเร็วเพื่อ$PATHนำหน้า crontab ปัจจุบัน:

# echo PATH=$PATH > tmp.cron
# echo >> tmp.cron
# crontab -l >> tmp.cron
# crontab tmp.cron

crontab ที่ได้จะมีลักษณะคล้ายกับคำตอบของ chrissygormley โดยมี PATH กำหนดไว้ก่อนกฎ crontab


22

คุณควรใส่เส้นทางแบบเต็มในcrontabไฟล์. นั่นคือตัวเลือกที่ปลอดภัยที่สุด
หากคุณไม่ต้องการทำเช่นนั้นคุณสามารถใส่สคริปต์ wrapper รอบ ๆ โปรแกรมของคุณและตั้งค่า PATH ไว้ที่นั่น

เช่น

01 01 * * * command

กลายเป็น:

01 01 * * * /full/path/to/command

นอกจากนี้สิ่งที่เรียกจากcronควรระมัดระวังเกี่ยวกับโปรแกรมที่รันและอาจตั้งค่าตัวเลือกของตัวเองสำหรับPATHตัวแปร

แก้ไข:

หากคุณไม่ทราบว่าคำสั่งอยู่ที่ใดที่คุณต้องการดำเนินการwhich <command>จากเชลล์ของคุณและคำสั่งนั้นจะบอกเส้นทางให้คุณทราบ

EDIT2:

ดังนั้นเมื่อโปรแกรมของคุณทำงานสิ่งแรกที่ควรทำคือตั้งค่าPATHและตัวแปรที่จำเป็นอื่น ๆ (เช่นLD_LIBRARY_PATH) เป็นค่าที่จำเป็นสำหรับสคริปต์ในการทำงาน
โดยทั่วไปแทนที่จะคิดว่าจะแก้ไขสภาพแวดล้อม cron อย่างไรเพื่อให้เหมาะสมกับโปรแกรม / สคริปต์ของคุณมากขึ้น - ให้สคริปต์ของคุณจัดการกับสภาพแวดล้อมที่กำหนดโดยการตั้งค่าที่เหมาะสมเมื่อเริ่มต้น


1
หากในเส้นทางของคุณใช้ 'คำสั่งใด' และจะให้เส้นทางแบบเต็มแก่คุณ
Paul Whelan

@ Douglas Leeder - เมื่อคุณพูดว่าใส่เส้นทางแบบเต็มลงใน cron คุณหมายถึงใส่ลงใน crontab หรือไฟล์อื่นหรือไม่? หากเป็นเช่นนั้นคุณจะทำอย่างไรถ้าคำสั่ง cron คือ: '01 01 * * * command ' ขอบคุณ
chrissygormley

@chrissygormley - crontabใช่
Douglas Leeder

ขออภัยต้องมีความสับสน ฉันได้ทบทวนคำถามข้างต้นแล้ว
chrissygormley

16

การตั้งค่า PATH ก่อนบรรทัดคำสั่งใน crontab ของฉันใช้งานได้สำหรับฉัน:

* * * * * PATH=$PATH:/usr/local/bin:/path/to/some/thing

ชอบวิธีนี้ หรือระบุเส้นทางแบบเต็มของสคริปต์
zw963

5
ฉันไม่คิดว่าเส้นทางจะเติบโตไปเรื่อย ๆ ทุกครั้งที่วิ่งจะเป็นสภาพแวดล้อมใหม่พร้อมสำเนาใหม่ของ PATH ...
jjcf89

สามารถยืนยันได้ว่า @ jjcf89 ถูกต้อง PATH มีความสดใหม่ในการวิ่งแต่ละครั้ง
electrovir

14

การเพิ่มนิยาม PATH ลงใน crontab ผู้ใช้ด้วยค่าที่ถูกต้องจะช่วยได้ ... ฉันเติมของฉันด้วย:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

และก็เพียงพอที่จะทำให้สคริปต์ของฉันทำงานได้ทั้งหมด ... รวมเส้นทางที่กำหนดเองไว้ที่นั่นหากคุณต้องการ


1
สำหรับ crontab ผู้ใช้นี่ควรเป็นคำตอบที่ถูกต้อง ไม่ใช่ทุกคนในระบบที่แก้ไข/etc/crontabได้ นี่คือคำตอบที่ง่ายที่สุดในระดับผู้ใช้ ทำได้ดีมาก @ Treviño โหวตสิ่งนี้ถ้าคุณเห็นด้วย
frederickjh

14

ทำให้ตัวแปรของคุณทำงานให้คุณซึ่งจะอนุญาตให้เข้าถึง t

กำหนดเส้นทางของคุณใน /etc/profile.d/*.sh

ตัวแปรสภาพแวดล้อมทั้งระบบ

ไฟล์ที่มีนามสกุล. sh ในไดเร็กทอรี /etc/profile.d จะถูกเรียกใช้งานเมื่อใดก็ตามที่มีการป้อน bash login เชลล์ (เช่นเมื่อล็อกอินจากคอนโซลหรือผ่าน ssh) รวมถึง DisplayManager เมื่อเซสชันเดสก์ท็อปโหลด

ตัวอย่างเช่นคุณสามารถสร้างไฟล์ /etc/profile.d/myenvvars.sh และตั้งค่าตัวแปรเช่นนี้:

export JAVA_HOME=/usr/lib/jvm/jdk1.7.0
export PATH=$PATH:$JAVA_HOME/bin

ดำเนินการ crontab ด้วยตัวเลือกการเข้าสู่ระบบ!

CRONTAB เรียกใช้สคริปต์หรือคำสั่งด้วยตัวแปรสภาพแวดล้อม

0 9 * * * cd /var/www/vhosts/foo/crons/; bash -l -c 'php -f ./download.php'
0 9 * * * cd /var/www/vhosts/foo/crons/; bash -l -c download.sh

11

ปัญหา

สคริปต์ของคุณทำงานเมื่อคุณเรียกใช้จากคอนโซล แต่ล้มเหลวใน cron

สาเหตุ

crontab ของคุณไม่มีตัวแปรเส้นทางที่ถูกต้อง (และอาจเป็นเชลล์)

สารละลาย

เพิ่มเชลล์ปัจจุบันของคุณและกำหนดเส้นทาง crontab

สคริปต์ที่จะทำเพื่อคุณ

#!/bin/bash
#
# Date: August 22, 2013
# Author: Steve Stonebraker
# File: add_current_shell_and_path_to_crontab.sh
# Description: Add current user's shell and path to crontab
# Source: http://brakertech.com/add-current-path-to-crontab
# Github: hhttps://github.com/ssstonebraker/braker-scripts/blob/master/working-scripts/add_current_shell_and_path_to_crontab.sh

# function that is called when the script exits (cleans up our tmp.cron file)
function finish { [ -e "tmp.cron" ] && rm tmp.cron; }

#whenver the script exits call the function "finish"
trap finish EXIT

########################################
# pretty printing functions
function print_status { echo -e "\x1B[01;34m[*]\x1B[0m $1"; }
function print_good { echo -e "\x1B[01;32m[*]\x1B[0m $1"; }
function print_error { echo -e "\x1B[01;31m[*]\x1B[0m $1"; }
function print_notification { echo -e "\x1B[01;33m[*]\x1B[0m $1"; }
function printline { 
  hr=-------------------------------------------------------------------------------------------------------------------------------
  printf '%s\n' "${hr:0:${COLUMNS:-$(tput cols)}}"
}
####################################
# print message and exit program
function die { print_error "$1"; exit 1; }

####################################
# user must have at least one job in their crontab
function require_gt1_user_crontab_job {
        crontab -l &> /dev/null
        [ $? -ne 0 ] && die "Script requires you have at least one user crontab job!"
}


####################################
# Add current shell and path to user's crontab
function add_shell_path_to_crontab {
    #print info about what's being added
    print_notification "Current SHELL: ${SHELL}"
    print_notification "Current PATH: ${PATH}"

    #Add current shell and path to crontab
    print_status "Adding current SHELL and PATH to crontab \nold crontab:"

    printline; crontab -l; printline

    #keep old comments but start new crontab file
    crontab -l | grep "^#" > tmp.cron

    #Add our current shell and path to the new crontab file
    echo -e "SHELL=${SHELL}\nPATH=${PATH}\n" >> tmp.cron 

    #Add old crontab entries but ignore comments or any shell or path statements
    crontab -l | grep -v "^#" | grep -v "SHELL" | grep -v "PATH" >> tmp.cron

    #load up the new crontab we just created
    crontab tmp.cron

    #Display new crontab
    print_good "New crontab:"
    printline; crontab -l; printline
}

require_gt1_user_crontab_job
add_shell_path_to_crontab

แหล่ง

https://github.com/ssstonebraker/braker-scripts/blob/master/working-scripts/add_current_shell_and_path_to_crontab.sh

ตัวอย่างผลลัพธ์

add_curent_shell_and_path_to_crontab.sh เอาต์พุตตัวอย่าง


3

บน AIX cron ของฉันเลือกตัวแปรสภาพแวดล้อมจาก / etc / environment โดยไม่สนใจสิ่งที่ตั้งค่าใน. profile

แก้ไข: ฉันยังตรวจสอบกล่องลินุกซ์สองสามกล่องที่มีอายุต่างกันและสิ่งเหล่านี้ดูเหมือนจะมีไฟล์นี้เช่นกันดังนั้นจึงไม่น่าจะเฉพาะ AIX

ฉันตรวจสอบสิ่งนี้โดยใช้คำแนะนำ cron ของ joemaller และตรวจสอบผลลัพธ์ก่อนและหลังการแก้ไขตัวแปร PATH ใน / etc / environment


3

หากคุณไม่ต้องการทำการแก้ไขแบบเดียวกันในที่ต่างๆให้ทำดังนี้:

* * * * * . /home/username/.bashrc && yourcommand all of your args

. ช่องว่างจากนั้นพา ธ ไปยัง. bashrc และคำสั่ง && เป็นเวทมนตร์ที่จะทำให้สภาพแวดล้อมของคุณเปลี่ยนไปเป็น bash shell ที่กำลังทำงานอยู่ เช่นกันหากคุณต้องการให้เชลล์ทุบตีเป็นความคิดที่ดีที่จะมีบรรทัดใน crontab ของคุณ:

SHELL=/bin/bash

หวังว่าจะช่วยใครสักคน!


2

สภาพแวดล้อมดีฟอลต์สำหรับงาน cron นั้นเบาบางมากและอาจแตกต่างจากสภาพแวดล้อมที่คุณพัฒนาสคริปต์ python ของคุณมากสำหรับสคริปต์ที่อาจรันใน cron ควรตั้งค่าสภาพแวดล้อมใด ๆ ที่คุณต้องใช้อย่างชัดเจน ในไฟล์ cron รวมพา ธ แบบเต็มไปยังไฟล์ปฏิบัติการ python และไปยังสคริปต์ python ของคุณ


2

ฉันรู้ว่าสิ่งนี้ได้รับคำตอบแล้ว แต่ฉันคิดว่าคำตอบนี้จะมีประโยชน์กับบางคน ฉันมีปัญหาคล้ายกันที่เพิ่งแก้ไข ( พบที่นี่ ) และนี่คือไฮไลท์ของขั้นตอนที่ฉันทำเพื่อตอบคำถามนี้:

  1. ตรวจสอบให้แน่ใจว่าคุณมีตัวแปรที่ต้องการใน PYTHONPATH (พบที่นี่และที่นี่และสำหรับข้อมูลเพิ่มเติมที่นี่) ภายใน. profile หรือ. bash_profile สำหรับเชลล์ใด ๆ ที่คุณต้องการทดสอบสคริปต์ของคุณเพื่อให้แน่ใจว่าทำงานได้

  2. แก้ไข crontab ของคุณเพื่อรวมไดเร็กทอรีที่จำเป็นในการรันสคริปต์ของคุณในงาน cron (พบได้ที่นี่และที่นี่)

    a) อย่าลืมรวมไดเรกทอรีรากไว้ในตัวแปร PATH (.) ตามที่อธิบายไว้ที่นี่ (โดยทั่วไปถ้าคุณเรียกใช้ไฟล์ปฏิบัติการด้วยคำสั่งของคุณจำเป็นต้องสามารถค้นหารูทหรือไดเร็กทอรีที่เก็บไฟล์ปฏิบัติการได้) และอาจเป็นสิ่งเหล่านี้ (sbin /: / bin: / usr / sbin: / usr / bin)

  3. ในไฟล์ crontab ของคุณสร้าง cronjob ที่จะเปลี่ยนไดเร็กทอรีเป็นไดเร็กทอรีที่คุณรันสคริปต์สำเร็จก่อนหน้านี้ (เช่น Users / user / Documents / foo)

    ก) สิ่งนี้จะมีลักษณะดังต่อไปนี้:

    * * * * cd /Users/user/Documents/foo; bar -l doSomething -v 
    

2

@Trevino: คำตอบของคุณช่วยฉันแก้ปัญหาของฉัน อย่างไรก็ตามสำหรับผู้เริ่มต้นพยายามให้แนวทางทีละขั้นตอน

  1. รับการติดตั้ง java ปัจจุบันของคุณผ่านทาง $ echo $JAVA_HOME
  2. $ crontab -e
  3. * * * * * echo $PATH- สิ่งนี้ช่วยให้คุณเข้าใจว่าค่า PATH ที่ crontab ใช้ในปัจจุบันคืออะไร เรียกใช้ crontab และคว้าค่า $ PATH ที่ crontab ใช้
  4. ตอนนี้แก้ไข crontab อีกครั้งเพื่อตั้งค่าเส้นทาง java bin ที่คุณต้องการ: a) crontab -e; b) PATH=<value of $JAVA_HOME>/bin:/usr/bin:/bin(เป็นเส้นทางตัวอย่าง); c) ตอนนี้งาน / สคริปต์ตามกำหนดการของคุณเช่น*/10 * * * * sh runMyJob.sh &; d) ลบออกecho $PATHจาก crontab เนื่องจากไม่จำเป็นในตอนนี้

2

ตั้งค่า PATH ที่ต้องการใน cron ของคุณ

crontab -e

แก้ไข: กด i

PATH=/usr/local/bin:/usr/local/:or_whatever

10 * * * * your_command

บันทึกและออก :wq


1

วิธีแก้ปัญหาที่ง่ายที่สุดที่ฉันพบมีดังนี้:

* * * * * root su -l -c command

ตัวอย่างนี้เรียกใช้suในฐานะผู้ใช้รูทและเริ่มต้นเชลล์ด้วยสภาพแวดล้อมแบบเต็มของผู้ใช้รวมถึง $ PATH ซึ่งตั้งค่าราวกับว่าพวกเขาเข้าสู่ระบบมันทำงานเหมือนกันบน distros ที่แตกต่างกันมีความน่าเชื่อถือมากกว่าการจัดหา. bashrc (ซึ่งไม่ได้ผล me) และหลีกเลี่ยงเส้นทางเฉพาะที่เข้ารหัสซึ่งอาจเป็นปัญหาได้หากคุณกำลังให้ตัวอย่างหรือเครื่องมือตั้งค่าและไม่รู้ว่าไฟล์ distro หรือเค้าโครงไฟล์ใดในระบบของผู้ใช้

คุณยังสามารถระบุชื่อผู้ใช้หลังจากนั้นsuหากคุณต้องการผู้ใช้อื่นที่ไม่ใช่รูท แต่คุณควรปล่อยrootพารามิเตอร์ไว้ก่อนsuคำสั่งเนื่องจากจะทำให้แน่ใจว่าsuมีสิทธิ์เพียงพอที่จะเปลี่ยนไปใช้ผู้ใช้ที่คุณระบุ


-3

คุณควรใช้webminขั้นตอนเหล่านี้ในการตั้งPATHค่า:

System
  -> Scheduled Cron Jobs
       -> Create a new environment variable
            -> For user: <Select the user name>
            -> Variable name: PATH
            -> Value: /usr/bin:/bin:<your personal path>
            -> Add environment variable: Before all Cron jobs for user
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.