Cron doesn't use the path of the user whose crontab it is and, instead, has its own. It can easily be changed by adding PATH=/foo/bar
at the beginning of the crontab, and the classic workaround is to always use absolute paths to commands run by cron, but where is cron's default PATH defined?
I created a crontab with the following contents on my Arch system (cronie 1.5.1-1) and also tested on an Ubuntu 16.04.3 LTS box with the same results:
$ crontab -l
* * * * * echo "$PATH" > /home/terdon/fff
That printed:
$ cat fff
/usr/bin:/bin
But why? The default system-wide path is set in /etc/profile
, but that includes other directories:
$ grep PATH= /etc/profile
PATH="/usr/local/sbin:/usr/local/bin:/usr/bin"
There is nothing else relevant in /etc/environment
or /etc/profile.d
, the other files I thought might possibly be read by cron:
$ grep PATH= /etc/profile.d/* /etc/environment
/etc/profile.d/jre.sh:export PATH=${PATH}:/usr/lib/jvm/default/bin
/etc/profile.d/mozilla-common.sh:export MOZ_PLUGIN_PATH="/usr/lib/mozilla/plugins"
/etc/profile.d/perlbin.sh:[ -d /usr/bin/site_perl ] && PATH=$PATH:/usr/bin/site_perl
/etc/profile.d/perlbin.sh:[ -d /usr/lib/perl5/site_perl/bin ] && PATH=$PATH:/usr/lib/perl5/site_perl/bin
/etc/profile.d/perlbin.sh:[ -d /usr/bin/vendor_perl ] && PATH=$PATH:/usr/bin/vendor_perl
/etc/profile.d/perlbin.sh:[ -d /usr/lib/perl5/vendor_perl/bin ] && PATH=$PATH:/usr/lib/perl5/vendor_perl/bin
/etc/profile.d/perlbin.sh:[ -d /usr/bin/core_perl ] && PATH=$PATH:/usr/bin/core_perl
There is also nothing relevant in any of the files in /etc/skel
, unsurprisingly, nor is it being set in any /etc/cron*
file:
$ grep PATH /etc/cron* /etc/cron*/*
grep: /etc/cron.d: Is a directory
grep: /etc/cron.daily: Is a directory
grep: /etc/cron.hourly: Is a directory
grep: /etc/cron.monthly: Is a directory
grep: /etc/cron.weekly: Is a directory
/etc/cron.d/0hourly:PATH=/sbin:/bin:/usr/sbin:/usr/bin
So, where is cron's default PATH for user crontabs being set? Is it hardcoded in cron
itself? Doesn't it read some sort of configuration file for this?
cron
to look at/etc/profile
, or care about any particular shell. A better question is why doesn'tcron
readPATH
fromlogin.defs
(on Linux) orlogin.conf
(on *BSD). I suppose it's ultimately an implementation detail./etc/profile
because it uses the same syntax (var=value
) ascron
itself, so it would be easy enough to do and/etc/profile
is, to my knowledge, very widespread. What surprised me is that I couldn't find it being set anywhere so it looked like it was hard coded. As is indeed the case, as Stephen explained below.zsh
as their interactive shell don't care about/etc/profile
(which is specific tobash
)profile
files are only read by login shells, anyway. These may, or may not be interactive.strings
against a program can help find these hard-coded values, too.