58

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?

csny
  • 1,505

6 Answers6

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.

madumlao
  • 1,716
  • 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 03 '14 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 03 '14 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 03 '14 at 15:42
  • 5
    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 04 '14 at 03:34
  • 1
    Great. Thanks Madunlao. After I manually added bin file folder to ~/.bash_profile, my cronjob works well. – Lane Jun 30 '16 at 06:56
  • Which $PATH do i have to change? ~/.profile and what do i have to add? – ttt Apr 29 '17 at 04:03
36

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
itsafire
  • 461
  • 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. – Danila Vershinin May 30 '21 at 07:55
  • The tilde is working with cron on MacOS, but seems not to work on Debian (buster) as you noted. Thanks. – itsafire May 31 '21 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
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

mistige
  • 139
0

This works on Ubuntu 22.04.3 LTS:

* * * * * export PATH="${HOME}/bin:${PATH}"; echo "${PATH} ${HOME}" >> /tmp/crontab

This example does not do anything very useful but demonstrates you can read and set some environment variables on a per-job basis.

davejagoda
  • 105
  • 5