我写了一个shell脚本来持续监控Nagios服务状态(参见这问题),如下:
#!/bin/bash
RCPT="[email protected]"
service nagios status | grep [0-9]
if [ $? -eq 0 ]
then
exit 0
else
service nagios start
echo "Hello, Nagios Service has been started, please confirm." | mail -s "Nagios Service Stopped" $RCPT
fi
当从命令行执行上述脚本时,它将按预期工作 - 如果在服务状态输出中找不到 PID,它将发送一封电子邮件,否则退出。但是,当我在 中添加此脚本时crontab
,每次执行时它都会发出通知。
可能存在什么问题以及如何克服它?
答案1
默认情况下,cron
运行非常受限制的命令PATH
,其中不包括您的service
命令。这可能会生成导致电子邮件发送的非零返回代码。
除非文件中另有指定crontab
,否则命令在路径下运行:
PATH=/usr/bin:/bin
相比之下,service
通常 in usr/sbin
which 不在默认值中PATH
:
# type service
service is /usr/sbin/service
常见的解决方案有两种:
PATH
在您或您的脚本顶部附近提供包含您需要的内容的声明crontab
。明确指定所有路径。
前者更方便。后者被认为更安全。
如何调试 crontab 命令
在具有设置良好的电子邮件系统的系统上,cron
只要 cron 作业中发生错误,就会向用户发送包含脚本输出的电子邮件。然而,并非所有系统都具有设置良好的电子邮件。 cron
还将向记录器发送错误通知,但记录器对它们的处理取决于记录器的配置,该配置可能是不透明的。
在这些情况下,请尝试在 cron 命令运行时自行收集所有错误消息,但更改 crontab 行。使用类似的东西:
1 2 * * * /path/to/myscript >>/tmp/myscript.log 2>&1
这会将 stdout 和 stderr 重定向到日志文件/tmp/myscript.log
。命令运行后,检查此日志文件。
答案2
您可以将输出重定向到以下/dev/null
内容(我为我的雷鸟应用程序执行此操作):
30 05 * * * /usr/bin/thunderbird >/dev/null 2>&1
>>
或者使用附加操作将其重定向到文件:
30 05 * * * /usr/bin/thunderbird >>/tmp/mycron.log 2>&1
笔记:
您可以使用服务文件的完整路径(例如/etc/init.d/NetworkManager status
)而不是service NetworkManager status
.
推荐:
最好用 和pidof
命令的组合来观察你的软件ps -p
,因为服务文件会检查/var/run/
目录下的 pid 文件,如果你的程序被意外杀死(例如 Signal 9),它的 pid 文件将会存在!然而智能服务文件会在status
功能上检查这种情况。
例如:
while :; do
pid=$(pidof SOFTWARE)
watch=$(ps -p ${pid} >/dev/null 2>&1 && echo $?)
[[ ${watch} -ne 0 ]] && service SOFTWARE restart
sleep 3
done