Linux crond不執行的原因

為了定時監控linux系統CPU、內存、負載的使用情況,寫了Linux Shell腳本,當達到一定值得時候,定時發送郵件通知。但是,讓crond來周期性執行腳本發送郵件通知時,遇到了問題,在crontab -e里面加入了執行腳本之后,發現腳本并沒有執行。

可是,通過手動執行Shell腳本命令(./mimvp-email.sh)是正常的,因為手動執行腳本可以默認獲取Linux的環境變量,但通過Crontab做的定時任務,則無法獲取環境變量。

分析了原因,crond不執行的原因主要有以下幾個方面:

1、crond服務沒啟動

ps?-ef?|?grep?-v?grep?|?grep?crond?????????//?查看crond服務是否運行  service?crond?start???????????//關閉服務  service?crond?stop???????????//關閉服務  service?crond?restart???????//重啟服務  service?crond?reload???????//重新載入配置

2、用戶沒有執行crond的權限

vim ?/etc/cron.deny?文件用來控制哪些用戶不能執行crond服務的功能。

可以將自己從文件中刪去,或者聯系root

3、crontab不提供所執行用戶的環境變量

解決方法:在腳本中加入下面這一行:

. /etc/profile
. ~/.bash_profile

4、沒有使用絕對路徑

這里的絕對路徑包括腳本中的路徑和crond命令中的路徑兩個方面,例如:

*/10 * * * * sh?/root/script/mysql_files_monitor.sh?&

5、如果上面都沒有解決問題的話可以再找找問題:

1)去郵件看看,在這個過程中用戶應該會收到郵件,比如收到這樣的提示:

vim /var/spool/mail/root

You have mail in /var/spool/mail/root

去看看里面就有crond的內容

文件太大打不開,可以截取最后1000行查看

tail -n 1000 /var/spool/mail/root > aaa.txt ?&& ?vim aaa.txt

2)在腳本里面加入output用來調試

可以在crontab的腳本里面添加個

echo $PATH > /tmp/test.log

對比和終端下執行腳本的echo $PATH

6、crond進程太多,全部殺死重啟crond服務

#!/bin/bash
for i in $(ps -elf | grep -v grep | grep crond | awk -F ” ” ‘{print $4}’?); do
? ? ?kill -9 ?$i
done

使用root執行重啟,后問題解決:

service crond restart

7、crond防止腳本周期內未執行完重復執行

個人體會:?flock -xn my.lock cmd
my.lock是一個文件,可以是任意文件,可以新建一個空文件
當flock 獲得鎖后就會執行后面的 cmd

測試過程:

$1: flock -xn my.lock sleep 20
$2: flock -xn my.lock ls

只有當1返回后, 2的ls才會成功

如果某腳本要運行30分鐘,可以在Crontab里把腳本間隔設為至少一小時來避免沖突。而比較糟的情況是可能該腳本在執行周期內沒有完成,接著第 二個腳本又開始運行了。如何確保只有一個腳本實例運行呢?一個好用的方法是利用lockf(FreeBSD 8.1下為lockf,CentOS ?5.5下為flock),在腳本執行前先檢測能否獲取某個文件鎖,以防止腳本運行沖突。

lockf 參數如下

-k:一直等待獲取文件鎖。

-s:silent,不發出任何信息,即使拿不到文件鎖。

-t seconds:設定timeout的時間是seconds秒,如果超過時間,則自動放棄。

以下crontab計劃任務執行前,需獲取臨時文件create.lock 文件鎖,crontab計劃任務的內容如下:

1?*/10 * * * * (lockf -s -t 0 /tmp/create.lock?/usr/bin/python /home/project/cron/create_tab.py ?>> /home/project/logs/create.log 2>&1)

若第一個實例在10分鐘內沒有運行完,第2個實例不會運行。我以前是通過Shell腳本來解決這個問題的,比如用while…do循環,然后放在后臺執行。但后來發現其實用flock或lockf方法更為簡單。

附上linux下的flock的用法:

flock (util-linux 2.13-pre7)
Usage: flock [-sxun][-w #] fd#
? ? ? ?flock [-sxon][-w #] file [-c] command…
? -s ?–shared ? ? Get a shared lock?
#共享鎖,在定向為某文件的FD上設置共享鎖而未釋放鎖的時間內,其他進程試圖在定向為此文件的FD上設置獨占鎖的請求失敗,而其他進程試圖在定向為此文件的FD上設置共享鎖的請求會成功
? -x ?–exclusive ?Get an exclusive lock?
#獨占或排他鎖,在定向為某文件的FD上設置獨占鎖而未釋放鎖的時間內,其他進程試圖在定向為此文件的FD上設置共享鎖或獨占鎖都會失敗。只要未設置-s參數,此參數默認被設置
? -u ?–unlock ? ? Remove a lock?
#手動解鎖,一般情況不必須,當FD關閉時,系統會自動解鎖,此參數用于腳本命令一部分需要異步執行,一部分可以同步執行的情況
? -n ?–nonblock ? Fail rather than wait?
#為非阻塞模式,當試圖設置鎖失敗,采用非阻塞模式,直接返回1,
? -w ?–timeout ? ?Wait for a limited amount of time
#設置阻塞超時,當超過設置的秒數,就跳出阻塞,返回1
? -o ?–close ? ? ?Close file descriptor before running command
? -c ?–command ? ?Run a single command string through the shell 執行其后的comand
? -h ?–help ? ? ? Display this text
? -V ?–version ? ?Display version
舉個例子執行如下腳本:

每天23:30的時候執行一個腳本,但是執行前必須要獲得排他文件鎖,否則無法執行命令

1?30 23 * * *?flock -xn /tmp/test.lock?-c ‘/usr/local/php test.php’

8、; 和 &&?區別

“;” 和 “&&”是有區別的

“;”:不管cmd1執行的結果如何,都執行cmd2

“&&”:只有cmd1執行返回的結果是成功的,才執行cmd2

cmd1 && cmd2; cmd3

– cmd1 is executed, if it succeeds, then execute?cmd2. and then cmd3 (regardless of cmd2 success or not)

– cmd1 is executed, if it fails, then cmd3 (cmd2 won’t be executed)

9、如果遇到shell語法錯誤

Syntax error: "(" unexpected

解決方法:

需指定shell解釋器命令:SHELL=/bin/bash(請參見上面 crontab編輯示例?SHELL=/bin/bash)

或者參見:?LINUX – BASH Syntax Error

如果遇到路徑錯誤

在 /var/spool/crontab/yanggang 中,添加了如下命令,在日志文件 /var/spool/mail/yanggang 中提示找不到 xxx.sh 路徑

30 * * * * ?/home/barry/top800/top10/top10_fruits/top10_all.sh

30 * * * *?bash?/home/barry/top800/top10/top10_fruits/top10_all.sh

這是因為你在crontab中使用了絕對路徑執行腳本?top10_all.sh,因此在腳本?top10_all.sh?中引用的其它腳本也都需要使用絕對路徑,才能被crontab找到并執行。

那么該如何避免絕對路徑呢,推薦采用如下格式:

30 * * * * cd /home/barry/top800/top10/top10_fruits/ && ./top10_all.sh(推薦用此方式)

先進入該目錄,然后在執行腳本;否則,執行腳本中的其它腳本都需要加絕對路徑

參考推薦:

CentOS 7.2上 crontab 計劃任務

linux定時運行命令腳本——crontab

CentOS crontab 定時任務不執行的解決

WordPress定時任務(wp-cron.php)造成主機CPU超標解決辦法。

? 版權聲明
THE END
喜歡就支持一下吧
點贊13 分享