57

I had a problem running a script from crontab. After some research I understood the problem was because PATH parameter doesn't include /sbin.

I looked what it does include in /etc/crontab:

PATH=/sbin:/bin:/usr/sbin:/usr/bin

As a test - simple cron job to print the PATH variable:

* * * * * echo $PATH &> /root/TMP.log

the output is:

cat /root/TMP.log
/usr/bin:/bin

I don't understand this behaviour... How do I set the PATH variable..? Or better - how to add paths to it?

2
  • 2
    It might be worth a moment to ask yourself why the cron user's PATH variable is limited. Maybe it has something to do with security? The alternative to expanding the PATH for all of your cron jobs is to use a complete path specification - it may be less risky.
    – Seamus
    May 31, 2021 at 15:06
  • 1
    @Seamus the snark is unnecessary
    – odigity
    Oct 23 at 14:55

5 Answers 5

58

While they are similar, a user crontab (edited using crontab -e) is different from and keeps a separate path from the system crontab (edited by editing /etc/crontab).

The system crontab has 7 fields, inserting a username before the command. The user crontab, on the other hand, has only 6 fields, going directly into the command immediately after the time fields.

Likewise, the PATH in the system crontab normally includes the /sbin directories, whereas the PATH in the user crontab does not. If you want to set PATH for the user crontab, you need to define the PATH variable in the user crontab.


A simple workaround for adding your regular PATH in shell commands in cron is to have the cronjob source your profile by running bash in a login shell. for example instead of

* * * * * some command

You can instead run

* * * * * bash -lc some command

That way if your profile sets the PATH or other environment variables to something special, it also gets included in your command.

6
  • 2
    Thanks, that explains it... But this way I can only set the PATH, and not edit, because PATH=/sbin:$PATH or similar doesn't work. I tried...
    – csny
    Aug 3, 2014 at 12:17
  • Yes, you would need to define the PATH from scratch in a case like this, which should be easy enough, since you know all of the commands that are run in your crontab, so you just need to take those into consideration.
    – beans
    Aug 3, 2014 at 12:47
  • @madumlao bash -lc doesn't help. I'm good for now with setting PATH manually, but if I install some scripts, I want them to be recognized in cronjobs without specifying full paths. I'm sure it is possible somehow, and bash -lc is on the way to a solution :)
    – csny
    Aug 3, 2014 at 15:42
  • 4
    bash -lc starts a login shell which sources your user's profile. This means that it uses the PATH set in ~/.bash_profile, ~/.profile, or ~/.bashrc... do you have the path set there? If so and it works ill update my answer for it
    – madumlao
    Aug 4, 2014 at 3:34
  • Great. Thanks Madunlao. After I manually added bin file folder to ~/.bash_profile, my cronjob works well.
    – Lane
    Jun 30, 2016 at 6:56
34

It is possible to set the PATH (or other parameters) in the cronjob line or on a single line. But you are not able to use shell expansion like PATH=$PATH:/usr/local/bin. The tilde (~) character as a shortcut for the home directory works on MacOS, but seems not to work on Linux (at least with debian/buster).

From the books:

An active line in a crontab is either an environment setting or a cron command. An environment setting is of the form: name = value where the white spaces around the equal-sign (=) are optional, and any subsequent non-leading white spaces in value is a part of the value assigned to name. The value string may be placed in quotes (single or double, but matching) to preserve leading or trailing white spaces.

See man 5 crontab for more information.

So this should work:

PATH=/bin:/usr/bin:/my/path/bin
5 3 * * * command_that_requires_my_path
2
  • 1
    Well noted about not being able to use shell expansion in the right-hand side of the environment assignment. Although tilde doesn't seem to work there also. May 30, 2021 at 7:55
  • The tilde is working with cron on MacOS, but seems not to work on Debian (buster) as you noted. Thanks.
    – itsafire
    May 31, 2021 at 11:53
14

If you need default system wide PATHs and other ENV variables (which defined in /etc/profile.d), just put the following:

* * * * * . /etc/profile; your cmd
2
1

I had the same problem and i found other way to run my script in crontab. I think the easiest way to run your program is to make an script that could cd to the directory of your program. Then call your program in that script.

this is an example of an script (script name=launcher.sh):

#!bin/bash
cd /home/pi/test
sudo python3 example.py

then, make your script executable:

chmod 755 launcher.sh

And at last, add your script to crontab

crontab -e

and add this line at the end:

@reboot sh /home/pi/test/launcher.sh

(I set the program to run at each reboot)

0

You can make cron do some logging for you, when you extend your command like this:

E.g. fire at XX:05 each time

5 * * * * /usr/bin/bash -x /path/to/script 2>&1 | tee -a /root/output.cron.txt

Review the log, and see what problems cron encounters.

HTH Michael

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .