-1

I have written a shell script in order to monitor Nagios service status continuously (See this question), which is as follows:

#!/bin/bash

RCPT="abc@xyz.com"

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

When above script is executed from command-line, it would work as expected - it would send an email if PID is not found in the service status output, else exits. But, when I added this script in crontab, it would dispatch a notification every time it is executed.

What might be the problem and how to overcome it?

2 Answers2

3

By default, cron runs commands with a very restricted PATH which would not include your service command. This could be what generates the non-zero return code that leads to the email being sent.

Unless specified otherwise in the crontab file, commands are run under the path:

PATH=/usr/bin:/bin

By contrast, service is generally in usr/sbin which is not in the default PATH:

# type service
service is /usr/sbin/service

There are two common solutions:

  1. Provide a PATH statement that contains what you need near the top of either your crontab or your script.

  2. Specify all paths explicitly.

The former is more convenient. The latter is considered more secure.

How to debug a crontab command

On a system with a well set-up email system, cron sends an email containing the script output to the user whenever an error occurs in a cron job. Not all systems, however, have well set-up email. cron will also send error notices to the logger but what the logger does with them depends on the logger's configuration which can be opaque.

In these cases, try to collect all error messages yourself when the cron command runs but altering the crontab line. Use something like:

1 2 * * *  /path/to/myscript >>/tmp/myscript.log 2>&1

This redirects both stdout and stderr to the log file /tmp/myscript.log. After the command runs, examine this log file.

John1024
  • 74,655
-1

You can redirect the output to the /dev/null like following (I do this for my thunderbird applications):

30 05 * * * /usr/bin/thunderbird >/dev/null 2>&1

Or redirect it to the file with >> operations which means append:

30 05 * * * /usr/bin/thunderbird >>/tmp/mycron.log 2>&1

NOTE: You can use full path of the service file (eg. /etc/init.d/NetworkManager status) instead of service NetworkManager status.

Recommendation:
It's better to watch your software with combination of pidof and ps -p commands, because service files will check pid file under /var/run/ directory and if your program was killed unexpectedly (Eg. Signal 9) it's pid file will exists! However smart service files will check this situation in status function.

For Example:

while :; do
       pid=$(pidof SOFTWARE)
       watch=$(ps -p ${pid} >/dev/null 2>&1 && echo $?)
       [[ ${watch} -ne 0 ]] && service SOFTWARE restart
       sleep 3
done