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" 便可)

一个小问题竟然花了几个小时查清楚缘由,可见平时以为简单的问题在实际应用过程当中仍是有不少坑的

相关文章
相关标签/搜索