I recently had to re-install 10.9.5 (default install) and am now finding that bash scripts that run perfectly from the command line (~/Me...) no longer work using crontab. I use crontab to invoke "Diskutil unmount volumeX" but am getting mail from cron saying "diskutil" command not found. Is it a PATH issue and if so how would I fix it. Thank you in advance for any help.
2 Answers
cron
uses /usr/bin:/bin
as the default PATH
and diskutil
is in /usr/sbin
.
Specify the full path to diskutil
or add a line like PATH=/usr/bin:/bin:/usr/sbin:/sbin
to the start of your crontab.
Enter which diskutil
to find its path, or enter echo $PATH
to find the path where your commands are working.
Question:
Is it a PATH issue and if so how would I fix it.
Answer to "Is this a PATH issue?":
It most probably is a "PATH issue". But the real issue is not knowing the true value of $PATH
that cron
uses. That is the issue this answer will address.
As a user of cron
, one of the things you should understand is that although cron
executes your crontab
instructions on your behalf, and under your userid, it does this within a different environment than you do as a "logged in" user.
Perhaps the easiest way to discover what your environment is when running a job from cron
is to ask cron
to tell you! That's easily done as follows:
% crontab -e
# in your editor, add the following line, then save & close your new crontab
* * * * * printenv > /Users/$USER/mycronenvironment.txt 2>&1
# now wait for the output:
% tail -f ~/mycronenvironment.txt
You'll want to stop this shortly, so edit and save your crontab
. Your output will resemble this:
SHELL=/bin/sh
USER=seamus
PATH=/usr/bin:/bin
PWD=/Users/seamus
SHLVL=1
HOME=/Users/seamus
LOGNAME=seamus
_=/usr/bin/printenv
Note the PATH
variable is limited to /usr/bin
& bin
. So - your cron
job will look nowhere else for a file. You may now wish to compare this environment against the one in your interactive login shell. Simply run printenv
from your login shell (zsh
on later model Macs):
% printenv
...
PATH=/opt/local/bin:/opt/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/VMware Fusion.app/Contents/Public:/Library/Apple/usr/bin
...
This difference in the PATH
environment variables explains the source of an "unknown command" error generated by cron
: the command is not on the PATH
of the shell used by cron
.
Answer to "How do I fix this?":
In general, there are two methods:
Use a full path specification for everything in your
crontab
For example :
/usr/sbin/diskutil unmount volumeX
Define (re-define)
PATH
in yourcrontab
And as usual there are numerous ways to do this. If you want to use your "logged-in user"
PATH
as thePATH
for your "cron user":% echo $PATH /opt/local/bin:/opt/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/VMware Fusion.app/Contents/Public:/Library/Apple/usr/bin % crontab -e # copy and paste the $PATH string at the top of the file as follows: PATH=/opt/local/bin:/opt/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/VMware Fusion.app/Contents/Public:/Library/Apple/usr/bin # save & close your `crontab` # you can re-activate the `printenv` cron job again to verify the new path
A variation on this approach could be as follows:
Create a file named (for example)
~/.cronpath
Put a single line in this file:
PATH=/usr/bin:/bin:<other folders>
where <other folders> is a colon-separated list of dirs you wish to add to the defaultPATH
.Source the file
~/.cronpath
at reboot in yourcrontab
:
@reboot . /Users/$USER/.cronpath ... # remainder of crontab entries