0

I have made (with a Stack Exchange help) a script that checks if the web application is available and restarts the web app daemon in order to get it running again (usually helps until I'm at work). It's supposed to run every hour.

I've added the following line to sudo crontab -e:

0 * * * * bash /usr/local/bin/test.sh

The contents of test.sh:

#!/bin/sh
HTTP_STATUS=$(lynx -head -source https://example.com |head -1 |awk '{print $2}')
calendar=$(date "+%d-%m-%Y - %H:%M")
LOG="Log is placed in /usr/local/bin/test.log"

if [ "$HTTP_STATUS" = "503" ]
then
    systemctl restart mydaemon

    echo "$calendar - site unavailable ($HTTP_STATUS). Daemon restarted." >> test.log
elif [ "$HTTP_STATUS" = "200" ]
then
    echo "$calendar - site available ($HTTP_STATUS)" >> test.log
else
    echo "$calendar - site status unknown ($HTTP_STATUS)" >> test.log
fi

I have two other scripts in scheduled in cron that work just fine, only that they run every midnight. All of my scripts have same permissions and same owner.

My test.log file is not updated every hour so I suppose the script doesn't run. Running the script manually creates log entries.

2

crontab runs scripts in a different environment from login shell; in particular, PATH could be different or undefined.

Try to use absolute path on the commands (lynx, head ...) You can get them with

which <command>

Moreover you should specify path for test.log.

  • The problem is that if I run the script manually, everything is fine. For some reason, cron doesn't run this particular script every hour. I have two other scripts that are similar and work properly. Edit: ah I understand what you mean now, sorry. I will try to put absolute paths in my script. – xtl Aug 6 '19 at 12:56
  • It worked, thanks. I had to put an absolute path to test.log - I assumed it would write log to the location of script file. – xtl Aug 6 '19 at 13:09
2

Your script is running just fine, but it writes to a file called test.log in the current directory. Since you never cd in your script, the current directory technically be anywhere, but it's most likely the user's home directory.

To write to test.log located elsewhere, either cd to the correct directory in the script, or provide the full path to the test.log file when redirecting to it.

Also note that you are doing needlessly many redirections to the output file. If all output from your if statement should be appended to the log file, you might as well do

if ...; then
   ...
elif ...; then
   ...
else
   ...
if >>/path/to/test.log

which would redirect all output from within the if statement to the file.

Or, if all output from the script should be redirected to the log file, you may as well redirect from the crontab with

0 * * * * bash /usr/local/bin/test.sh >>/path/to/test.log

(some crontabs support @hourly as a shortcut for writing 0 * * * * by the way, check man 5 crontab on your system).

Tag on 2>&1 after the redirection of standard output to the file to also redirect the standard error stream (i.e. ... >/path/to/test.log 2>&1).

Additionally, you have /bin/sh in the script's #! line, but you run the script with bash explicitly from the crontab. This is confusing. As far as I can see, there's nothing bash-specific in your script, so either run it with /bin/sh from crontab, or just make it executable and don't specify an interpreter on the command line in crontab to run it.


My take on your script:

#!/bin/sh

now=$(date "+%d-%m-%Y - %H:%M")
logfile=/usr/local/bin/test.log

status=$( lynx -head -source 'https://example.com' | awk 'FNR == 1 { print $2 }' )

case $status in
    503)
        systemctl restart mydaemon
        message='Daemon restarted, site was unavailable'
        ;;
    200)
        message='Site is available'
        ;;
    *)
        message='Site status is unknown'
esac

printf '%s: %s (status=%s)\n' "$now" "$message" "$status" >>"$logfile"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.