添加到 cron 时的 Shell 脚本问题

添加到 cron 时的 Shell 脚本问题

我写了一个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/sbinwhich 不在默认值中PATH

# type service
service is /usr/sbin/service

常见的解决方案有两种:

  1. PATH在您或您的脚本顶部附近提供包含您需要的内容的声明crontab

  2. 明确指定所有路径。

前者更方便。后者被认为更安全。

如何调试 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

相关内容