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?
cronto look at/etc/profile, or care about any particular shell. A better question is why doesn'tcronreadPATHfromlogin.defs(on Linux) orlogin.conf(on *BSD). I suppose it's ultimately an implementation detail. – Satō Katsura Oct 31 '17 at 13:02/etc/profilebecause it uses the same syntax (var=value) ascronitself, so it would be easy enough to do and/etc/profileis, 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. – terdon Oct 31 '17 at 13:05zshas their interactive shell don't care about/etc/profile(which is specific tobash) – Basile Starynkevitch Oct 31 '17 at 13:16profilefiles are only read by login shells, anyway. These may, or may not be interactive. – terdon Oct 31 '17 at 13:20stringsagainst a program can help find these hard-coded values, too. – jrw32982 Nov 02 '17 at 02:34crontabreads a configuration file is irrelevant to what configuration is used bycronitself:crontabis just a program that is used to update the database of job tables used bycronand signalcronwhen it has changed.cron(if the version in use is anywhere near standard) should be reading/etc/crontabat startup. – Jules Nov 08 '17 at 00:33/etc/profileuses the same syntax ascronfor setting the path, but note that it is written in a general purpose programming language that is able to manipulate references to variables and to evaluate generated code, so in the general case extracting the path information from it is much more complex than whatcrondoes with its own files. – Jules Nov 08 '17 at 00:38/etc/profileshould be written in POSIXshand is sourced (.) by POSIX compliant (or semi-compliant, like bash, zsh etc.) shells. Given that cron also usesshto run its commands, it would be trivial to source it each time it launches itssh. – terdon Nov 08 '17 at 08:29shis not the "user-specified" shell, it is the default shell on *nix systems and is usually either a simple POSIX-compliant shell likedash, or actual bourne-sh orbashrunning in POSIX mode. either way, cron defaults to/bin/shso it could just as well have defaulted to reading/etc/profileor, as Sato correctly pointed out,login.[defs|conf]. – terdon Nov 08 '17 at 10:17