Linux計劃任務crontab運行腳本不正確的問題

問題的由來

寫好的程序但願在崩潰以後可以自啓動,因而利用linux的crontab功能,添加一個計劃任務,每分鐘執行一個腳本查看須要監控的進程是否還在,若是不在則啓動之,不然不作任何事情。這麼一個簡單的腳本在crontab中運行和在shell終端手工運行的結果卻不同。linux

問題描述

如下是監控腳本/home/watch.sh的內容:shell

#!/bin/sh
shell_log_file=/home/start.log
pid_count=`pidof video_checkup | wc -w`
path=$(cd "$(dirname "$0")"; pwd)
run_command="${path}/video_checkup"
config_path="${path}/config.json"
if [ $pid_count -eq 0  ]; then
     echo `date +%Y-%m-%d_%H:%M:%S`" run $run_command $config_path" >> $shell_log_file
     $run_command $config_path
else
     echo `date +%Y-%m-%d_%H:%M:%S`" video_checkup already running" >> $shell_log_file
fi

在shell終端中執行crontab -e 命令添加以下語句:json

*/1 * * * *  /home/watch.sh >/dev/null 2>&1

表示該腳本每分鐘運行一次,腳本的邏輯很簡單就是檢查進程video_checkup如不存在則運行之,但是在實際測試中卻發現,video_checkup進程不斷增多,每分鐘都被運行了一次。bash

問題分析

經過調試發現腳本中 if [ $pid_count -eq 0  ]; then 每次都會進入並執行video_checkup程序,也就是說 $pid_count -eq 0 這個判斷每次都是true。將 $pid_count 的值導入到log文件中發現確實是0 。ssh


可是video_checkup明明在運行的啊,不多是0的,將watch.sh在shell命令行上手工執行倒是正常的結果($pid_count就是實際的正在運行的video_checkup進程個數的值)。通過google發現,在crontab計劃任務中執行腳本watch.sh的環境變量,和本身ssh登陸到shell中手工執行watch.sh的環境變量是不一樣的,因而乎在watch.sh中加入下面的語句:

echo `export` >> $shell_log_file  並分別在crontab中執行watch.sh,以及在ssh登陸的shell中手工執行watch.sh發現果真export的結果不同。

在crontab中執行watch.sh的時候log文件中顯示的export結果中PATH的值是: export PATH="/usr/bin:/bin"
而ssh登陸到shell以後手工執行watch.sh以後log文件中顯示的export結果中的PATH的值是: PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin" 這個影響大嗎,難道這個PATH變量對 pid_count=`pidof video_checkup | wc -w` 執行的結果會有影響?  ide


此時我想到有一種可能就是,pidof命令是在哪一個目錄下?  在ssh的shell環境中執行:測試

[root@172-28-246-152 video_checkup]# which pidof
/sbin/pidof

發現pidof命令是在 /sbin/目錄下,也就是說crontab運行的環境中 PATH="/usr/bin:/bin" 目錄中根本沒有pidof這個命令,那麼在crontab中執行 watch.sh中的 pid_count=`pidof video_checkup | wc -w` 就會失敗,可是竟然連一個錯誤都沒有報告,並且pid_count變量中還被賦值了,難道pidof命令找不到的時候這個語句也能返回值?

我在ssh的shell中構造一個不存在的pidof路徑,試一下:google

[root@172-28-246-152 video_checkup]# pid_count=`/xx/pidof video_checkup | wc -w`
-bash: /xx/pidof: No such file or directory

果真報錯說No such file or directory找不到命令,可是此時pid_count中是否有值呢? 再試一下:命令行

[root@172-28-246-152 video_checkup]# pid_count=`/xx/pidof video_checkup | wc -w` && echo $pid_count
-bash: /xx/pidof: No such file or directory
0

結果完全清楚了: 因爲crontab在後臺運行,因此pidof命令不存在,咱們根本看不到報錯信息,由於報命令不存在的信息是不會被經過管道傳遞給 wc -w  的,因此能夠說出錯的時候wc -w沒有收到任何輸入,可是其執行的結果倒是 0 那麼變量pid_count的值就是 0 了。  調試

問題解決

將ssh登陸以後的shell環境中的PATH賦值到watch.sh腳本中便可,這樣腳本在運行的時候就能夠正確找到 pidof 命令得出正確的結果了 (也即在腳本watch.sh的開始處加入代碼 PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin" 便可)

一個小問題竟然花了幾個小時查清楚緣由,可見平時以爲簡單的問題在實際應用過程當中仍是有不少坑的

相關文章
相關標籤/搜索