Linux中crontab定時任務未執行錯誤總結

dbasdk發表於2017-06-24
crontab 就是一個定時任務了。但有一些網友配置好crontab後發現第二天起來沒有執行指定任務了,那麼這個問題有許可權,限制等等原因,我們來給各位總結一下關於crontab不執行的解決辦法。


沒有按照規範寫以下的shell指令碼導致執行失敗透過CentOS中的定時任務執行shell指令碼失敗,進行排查:
1)手動執行shell指令碼(sh backup.sh)成功執行,排除sh指令碼的語法錯誤。
2)透過nano /etc/crontab命令檢視定時任務,發現除過執行sh的定時任務外,其他任務都能正常執行。檢查其程式碼,


發現對SHELL、PATH、MAILTO、HOME還沒有好好了解過,以往都是注意下面的時間規則,所以查了一下定義:
1)SHELL,變數的值指定shell 環境(此處預設為 bash shell); 
2)PATH,變數定義用來執行命令的程式路徑;
3)MAILTO,任務的輸出被郵寄給 MAILTO 變數定義的使用者名稱,如果變數被定義為空白字串,電子郵件就不會被寄出; 
4)HOME,變數可以用來設定在執行命令或指令碼時使用的主目錄;
隨後看到SHELL的定義先用env一下看一下系統預設shell是哪個地址,


[root@AY data]# env
HOSTNAME=AY
TERM=xterm
SHELL=/bin/bash
...
隨後開啟shell指令碼檢視,果然沒有對shell指令碼配置地址。好了,找到了一個問題,下面就根據文件說明在shell指令碼開始的地方打上該shell地址,如我的env是SHELL=/bin/bash,那麼shell指令碼開始就應該如下:

#!/bin/bash  
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin  
export PATH
新增完後重啟服務service crond restart,檢查指令碼執行情況,順利執行~

這次是按排除法檢查了錯誤原因,主要還是由於沒有按照規範寫下的shell指令碼導致執行失敗。

下面再列出幾個常見的沒有按規範編寫shell會出現的問題:

1)由於啟動指令碼用的是系統的crontab所以必須定義sh檔案的目錄以及具體日誌的具體路徑
2)注意使用加減法使用((num=$line+1))兩個括號來進行弱型別轉換
3)注意if判斷大小於使用[[]]來進行,例如:if [[ $count > 0 ]],等於則可以使用一個[]即可

問題解決思路:
1. 判斷crontab是否有執行過,你可以新增一個每分鐘執行的寫檔案的小指令碼進行測試,如果有記錄說明crontab本身服務沒有問題.
如: Feb 7 14:45:01 1280859075761a8Z crond[13638]: (root) CMD (/backuptoqiniu/backuptoqiniu.sh )這裡面應該是表示crontab已經成功執行了的,所以crontab服務沒有問題.
2. 其實有經驗多半就會知道crontab的執行是沒有相關環境變數的,解決辦法就是在指令碼中打日誌,另外預設將所有的命令採用全路徑的方式.
除錯方法:新增日誌檔案,將原來所有的echo 全部可以嘗試追加到日誌檔案,或者在crontab寫的時候追加日誌.
45 14 * * * /backuptoqiniu/backuptoqiniu.sh >> /tmp/out.log 2>&1
ases.sql" -u $MYSQL_USER -h $MYSQL_SERVER -p$MYSQL_PASS $DATEBASE > "$NOW-Datab
我就沒有看懂你這個是什麼,是不是自己的命令不在預設的系統命令裡面.

測試方法: 測試crontab的PATH與手動執行的PATH不一樣.
可以在crontab的指令碼里面新增個echo $PATH > /tmp/1.log
對比和你手動的終端下執行的echo $PATH

方法三,再看一個例子
crontab定時任務不執行的原因1、指令碼語法錯誤在crontab指令碼沒有定時執行的時候,首先需要檢查指令碼的語法有沒有出現問題。
2、環境變數問題有時我們建立了一個crontab,但是這個任務卻無法自動執行,而手動執行這個任務卻沒有問題,這種情況一般是由於在crontab檔案中沒有配置環境變數引起的。我們在手動執行任務時是在當前shell環境下進行的,程式能夠找到環境變數,而系統自動執行任務排程時,是不會載入任何環境變數的。因此,我們需要在shelll指令碼中提供所有必要的路徑和環境變數。

需要注意的主要有以下三點:
1)指令碼中涉及檔案路徑時寫全域性路徑;
2)指令碼執行要用到java或其他環境變數時,透過source命令引入環境變數,如:
cat start_cbp.sh
#!/bin/sh
source /etc/profile
export RUN_CONF=/home/d139/conf/platform/cbp/cbp_jboss.conf
/usr/local/jboss-4.0.5/bin/run.sh -c mev &
3)當手動執行指令碼OK,但是crontab死活不執行時。這時必須大膽懷疑是環境變數惹的禍,並可以嘗試在crontab中直接引入環境變數解決問題。如:


0 * * * * . /etc/profile;/bin/sh /var/www/java/audit_no_count/bin/restart_audit.sh
3、系統任務排程及使用者任務排程系統任務排程主要完成系統的一些維護操作,使用者任務排程主要完成使用者自定義的一些任務,可以將使用者任務排程放到系統任務排程來完成(不建議這麼做),但是反過來卻不行,root使用者的任務排程操作可以透過“crontab –uroot –e”來設定,也可以將排程任務直接寫入/etc/crontab檔案,需要注意的是,如果要定義一個定時重啟系統的任務,就必須將任務放到/etc/crontab檔案,即使在root使用者下建立一個定時重啟系統的任務也是無效的。

crontab定時任務不執行的解決辦法
1、檢視crontab執行記錄如果出現了crontab定時任務不執行的情況,首先需要定位問題,那麼就需要透過日誌來確定問題所在。

crontab的日誌位置一般位於/var/log/cron,利用下面的語句即可檢視日誌。
tail -f /var/log/cron
上面的/var/log/cron只會記錄是否執行了某些計劃的指令碼,但是具體執行是否正確以及指令碼執行過程中的一些資訊linux會透過郵件形式傳送到給該使用者。
對於root使用者該郵件記錄位於/var/spool/mail/root,透過以下命令可以檢視最近的crontab執行情況。
tail -f /var/spool/mail/root
mail郵件一般只會記錄指令碼執行成功與否,如果執行失敗,無法給出進一步的錯誤資訊,這時需要我們將語句執行的錯誤資訊重定向至檔案中,這樣可以很方便的檢視錯誤資訊。下面就給出了一個簡單的例子
0 6 * * * /root/script/ss.sh >> /root/for_crontab/mylog.log 2>&1
上述語句表示把錯誤輸出和標準輸出都輸出到mylog.log中,在執行的時候會將命令執行的相關資訊記錄至mylog.log檔案中。

2、解決問題在經過上一步的問題定位之後,就可以很容易找到問題並解決。

來源:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29734436/viewspace-2141219/,如需轉載,請註明出處,否則將追究法律責任。

相關文章