My Script Won’t Run from Cron!
This is a fairly common issue with running scripts from root cron: the script works perfectly when ran manually from command line, but fails in unexpected ways when running automatically from root cron.
There may be multiple reasons for this. However, by far the most common cause is that “/sbin” is not in the root path when the script is running from cron. And so various superuser commands you would normally find in an admin shell script, fail to execute. On occasion, the results can be disastrous
Checking your scripts for potentially numerous occurrences of superuser commands lacking the full path can be tedious. Here’s a simple one-liner to give you a hand:
script=/var/adm/bin/inventory_parser.sh ; echo "Found these problems: " ; find /sbin -maxdepth 1 -type f | awk -F'/' '{print $NF}' | while read command ; do grep "${command} " "${script}" | grep -v "/sbin/${command} " ; done ; echo "" ; echo "These probably should be changed to:" ; find /sbin -maxdepth 1 -type f | awk -F'/' '{print $NF}' | while read command ; do grep "${command} " "${script}" | grep -v "/sbin/${command} " | sed "s@${command} @/sbin/${command} @g" ; done
Sample run:
script=/var/adm/bin/inventory_parser.sh ; echo "Found these problems: " ; find /sbin -maxdepth 1 -type f | awk -F'/' '{print $NF}' | while read command ; do grep "${command} " "${script}" | grep -v "/sbin/${command} " ; done ; echo "" ; echo "These probably should be changed to:" ; find /sbin -maxdepth 1 -type f | awk -F'/' '{print $NF}' | while read command ; do grep "${command} " "${script}" | grep -v "/sbin/${command} " | sed "s@${command} @/sbin/${command} @g" ; done Found these problems: this_host_bcast=$(ifconfig | grep ${this_host_ip} | sort -u | tail -1 | awk -F':' '{print $3}' | awk '{print $1}') this_host_mask=$(ifconfig | grep ${this_host_ip} | sort -u | tail -1 | awk -F':' '{print $4}' | awk '{print $1}') this_host_nic=$(ifconfig | cut -c1-8 | egrep [a-z] | grep -v ^lo | while read nic ; do if [ `ifconfig ${nic} | These probably should be changed to: this_host_bcast=$(/sbin/ifconfig | grep ${this_host_ip} | sort -u | tail -1 | awk -F':' '{print $3}' | awk '{print $1}') this_host_mask=$(/sbin/ifconfig | grep ${this_host_ip} | sort -u | tail -1 | awk -F':' '{print $4}' | awk '{print $1}') this_host_nic=$(/sbin/ifconfig | cut -c1-8 | egrep [a-z] | grep -v ^lo | while read nic ; do if [ `/sbin/ifconfig ${nic} |
In the example below, we’ve found three lines in the script that would fail if you run this script from root cron, because the “ifconfig” command needs to be “/sbin/ifconfig”.
And, of course, probably a less painful and more aesthetically pleasing way of fixing the missing path issue with cron, is to set path within the script. If you script runs fine from command line, then check what you have in your PATH and add it to the script:
echo $PATH /usr/sbin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin #!/bin/bash PATH=/usr/sbin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
Another common issue that may prevent your cron job from completing is the use of the “%”. Output of cron jobs is commonly redirected to log files and the “%” used for the “date” command to generate the name of the output file. To fix the problem, just prepend every instance of “%” with a backslash “\”. Here’s an example of a cron job sending output to a filename generated by the “date” command:
5 0 * * * /usr/bin/pdsh -N -t 60 -u 120 -w ^/home/server_list_current_pdsh.txt "sudo su - root -c '/var/adm/bin/uptime.sh'" 2>/dev/null > /nfs/uptime/`date +'\%Y-\%m-\%d_\%H\%M\%S'`.csv