crontab PATH and USER

LinuxCronCrontab

Linux Problem Overview


I am new to scheduling tasks with cron and crontab. I am trying to schedule execution of a task as if I had logged on, opened a terminal, and executed it myself.

However, I scheduled a task to help me observe what $USER and $PATH a scheduled task is executing with, and this is what I found:

$ crontab -l
41 11 * * * echo "USER: $USER" > ~/Desktop/cron_env.log; echo "PATH: $PATH" >> ~/Desktop/cron_env.log
$ cat ~/Desktop/cron_env.log
USER:
PATH: /usr/bin:/bin

It appears as though $USER is not set, and $PATH is something very basic and/or default. On the contrary, this is what I see when I open a terminal (logged in) and echo this same information:

USER: aschirma
PATH: /usr/lib/jvm/java-6-sun/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/pkg/icetools/bin:/pkg/hwtools/bin:/pkg/netscape/bin:/pkg/gnu/bin

What do I need to do to make my crontab tasks run the way I want?

Linux Solutions


Solution 1 - Linux

According to "man 5 crontab" you can set environment variables in your crontab, by writing them before your cron lines.

There is also an example of a crontab so you just have to copy/paste it :

$ man 5 crontab | grep -C5 PATH | tail 
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow usercommand
17 * * * *  root  cd / && run-parts --report /etc/cron.hourly
25 6 * * *  root  test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7  root  test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )

So you can adjust your PATH or any environment variable to whatever you want. But this example seems enough for typical cases.

Solution 2 - Linux

In *ix, processes commonly inherit an environment from their parent process across fork+exec. They have the option of clearing the environment, but usually they don't. You can see the process tree with ps axf, and you can see the environment variables by using ps axfe.

cron is commonly not a child of someone's shell, so it'll often have a different environment from your interactive shell. There's a good chance cron's going to be intentionally clearing its own environment somehow for consistency though.

I like to test my cron jobs ("foo" for the sake of discussion) with the following in an interactive shell: env - ./foo This will actually clear out more env vars that cron does, but it makes it easier to get things going IMO, since what you're testing is more similar. You'll need to set any variables you're depending on (like $PATH), or replace them with something else - EG $USER becomes $(whoami).

I also like to write my bash scripts to use "set -eu" and "set -o pipefail". The -eu says "exit on a nonzero exit code, and exit on an undefined variable reference", and the pipefail says "don't return the last exit code in a pipeline, instead return the first exit code that's nonzero in a pipeline". In your case, the set -u might be particularly helpful.

Solution 3 - Linux

Remember crontab is a daemon or service, so is not like a user logged in or something. If you want to have your environment variables you will need to set them yourself. However, most of these variables are set by the shell from the /etc/profile path and then going into your custom variables into your $HOME directory.

You may be able to set some of them by "sourcing" your /etc/profile like:

41 11 * * * /home/<me>/cron_env.sh
Where cron_env.sh will contain something like:
#!/bin/sh
source /etc/profile
/usr/bin/env > /home/<me>/cron_env.log

Solution 4 - Linux

In our environment, we typically don't have this issue as root is the only cron allowed and each command is typically ran as an application specific user VIA a su -c command as:

su - myuser -c "/usr/local/scripts/app.sh" 2>&1

since the "-" option is specified we get myuser's profile and environment. We recently had an issue with a command that needed root's authority to complete successfully, so we just issued the command without the su -c. After some amount of research, it dawned on us that the easiest way to get root's environment is to use the same technique for root as we do for all other applications so we issued:

su - root -c "/usr/local/scripts/app.sh" 2>&1

Solution 5 - Linux

crontab is not a bash script, you can't use environment variables that are normally available in a shell.

Try moving all that code into a shebang'ed script file (one starting with the line "#!/bin/bash") and run that script in the crontab.

I'm not sure, but i think PATH (and maybe EMAIL if you set it) may be the only one you can access inside the crontab file .

EDIT: Check the crontab 5 man page, there quite a few environment variables aviable, all set by the cron daemon.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAdam SView Question on Stackoverflow
Solution 1 - LinuxJulien PalardView Answer on Stackoverflow
Solution 2 - Linuxuser1277476View Answer on Stackoverflow
Solution 3 - LinuxFreddyView Answer on Stackoverflow
Solution 4 - LinuxAlan KwiatkowskiView Answer on Stackoverflow
Solution 5 - LinuxKurzedMetalView Answer on Stackoverflow