2012-04-12 84 views
41

我是使用cron和crontab調度任務的新手。我試圖安排一個任務的執行,就像我已經登錄,打開一個終端並自己執行它一樣。crontab PATH和USER

不過,我計劃一個任務來幫我觀摩一下美元的計劃任務與執行用戶和$ PATH,這是我發現:

$ crontab -l 
41 11 * * * echo "USER: $USER" > ~/Desktop/cron_env.log; echo "PATH: $PATH" >> ~/Desktop/cron_env.log 
$ cat ~/Desktop/cron_env.log 
USER: 
PATH: /usr/bin:/bin 

看來好像$ USER沒有設置,$ PATH是非常基本的和/或默認的。相反,這是我所看到的,當我打開一個終端(登錄)和回聲相同的信息:

USER: aschirma 
PATH: /usr/lib/jvm/java-6-sun/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/pkg/icetools/bin:/pkg/hwtools/bin:/pkg/netscape/bin:/pkg/gnu/bin 

什麼我需要做的,使我的crontab任務運行我想要的方式?

回答

0

crontab不是bash腳本,你不能使用通常在shell中可用的環境變量。

嘗試將所有代碼移動到shebang'ed腳本文件(一行以「#!/ bin/bash」開頭),然後在crontab中運行該腳本。

我不確定,但我認爲PATH(也許是EMAIL,如果你設置的話)可能是唯一一個你可以在crontab文件裏面訪問的。

編輯:檢查crontab 5 man page,有很多可變的環境變量,都由cron守護進程設置。

+0

OP這裏。從cron啓動的腳本不會繼承正確的PATH。事實上,這正是我開始遇到問題的地方:從cron執行的bash腳本沒有在PATH中找到任何東西,因爲PATH不正確。 – 2012-04-12 18:28:15

+0

@AdamS這就是問題所在,它們繼承了cron守護進程提供的PATH(和其他一些變量),這與您從登錄shell獲得的守護進程不一樣,如果需要,可以在您的crontab文件中設置PATH。 – KurzedMetal 2012-04-12 18:33:29

+0

從手冊頁:'值字符串不被解析爲環境替換或替換變量,因此像PATH = $ HOME/bin:$ PATH這樣的行將不會像您所期望的那樣工作。「 – blujay 2015-10-14 16:29:13

4

還記得crontab是一個守護進程或服務,所以不像用戶登錄什麼的。如果你想擁有你的環境變量,你需要自己設置它們。然而,這些變量中的大部分都是由shell從/ etc/profile路徑設置的,然後進入你的自定義變量到你的$ HOME目錄中。

您可以通過「採購」,設置一些人喜歡你的/ etc/profile文件:

 
41 11 * * * /home/<me>/cron_env.sh 
cron_env.sh將包含類似:
 
#!/bin/sh 
source /etc/profile 
/usr/bin/env > /home/<me>/cron_env.log 

+0

上述所有內容都不適用於我,所以我只是在我的bash文件中添加了源代碼,它工作正常!謝謝 – 2016-09-01 11:48:51

15

在* IX,工藝中常用繼承的環境他們的父級流程跨fork + exec。他們可以選擇清理環境,但通常他們不會。您可以使用ps axf來查看進程樹,並且可以使用ps axfe來查看環境變量。

cron通常不是某人shell的孩子,所以它通常與交互式shell有不同的環境。有一個很好的機會cron會故意清除自己的環境,但爲了保持一致性。

我喜歡在交互式shell下面來測試我的cron作業(爲便於討論「富」): ENV - ./foo 這實際上明確了更多的env瓦爾那cron的做法,但它讓事情變得更容易IMO,因爲你正在測試的是更類似的東西。你需要設置你所依賴的任何變量(比如$ PATH),或者用別的東西替換它們 - EG $ USER變成$(whoami)。

我也喜歡寫我的bash腳本來使用「set -eu」和「set -o pipefail」。 -eu表示「退出非零退出代碼並退出未定義的變量引用」,並且pipefail表示「不返回管道中的最後退出代碼,而是返回流水線中非零的第一個退出代碼」 。在你的情況下,set -u可能會特別有用。

+1

+1進行測試......我'人env''d尋找關於單破折號的信息。我希望它已經包含在'-i,--ignore-environment'行中,而不是位於描述部分的底部,在那裏我完全掩蓋了它。 – 2015-09-14 18:47:05

66

根據「man 5 crontab」,你可以在crontab中設置環境變量,方法是在你的cron行之前寫入環境變量。

還有一個crontab,所以你只需要複製的例子/粘貼:

$ man 5 crontab | grep -C5 PATH | tail 
# and files in /etc/cron.d. These files also have username fields, 
# 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 usercommand 
17 * * * * root cd/&& run-parts --report /etc/cron.hourly 
25 6 * * * root test -x /usr/sbin/anacron || (cd/&& run-parts --report /etc/cron.daily) 
47 6 * * 7 root test -x /usr/sbin/anacron || (cd/&& run-parts --report /etc/cron.weekly) 

所以,你可以調整你的路徑,或任何你想要的任何環境變量。但這個例子對於典型案例來說似乎足夠了

+6

有沒有辦法像'PATH = $ PATH:/ usr/local/bin'? – CMCDragonkai 2015-11-29 15:47:55

+4

@CMCDragonkai:根據'man 5 crontab',「值字符串不被解析用於環境替換或替換變量」。但是,您應該將代碼寫入單個可執行文件(通常是'.sh',但爲什麼不是C ou Python?),從crontab調用您的可執行文件,並讓可執行文件本身增加其$ PATH。 – 2015-12-01 14:04:35

+0

這爲我解決了https://community.letsencrypt.org/t/letsencrypt-renew-not-working-with-cronjob-manually-it-works/16738/8。 – 2017-01-30 14:27:24

2

在我們的環境中,我們通常沒有這個問題,因爲根是唯一允許cron和每個命令通常跑了作爲一個應用程序特定用戶通過蘇-c命令:因爲

su - myuser -c "/usr/local/scripts/app.sh" 2>&1 

指定了「 - 」選項,我們獲得myuser的配置文件和環境。我們最近遇到了需要root權限才能成功完成的命令,所以我們只是在沒有su -c的情況下發布命令。研究一定量後,明白了我們,獲得root的環境的最簡單的方法是在我們爲所有其他應用程序做使用相同的技術爲根,所以我們發出:

su - root -c "/usr/local/scripts/app.sh" 2>&1