In this tutorial, we’re going to learn how the PATH variable of the cron environment looks like and how to provide the desired PATH to the job.
2. Illustrative Example to State the Problem
Let’s write a simple bash script to print ‘Hello World’ and call it hello:
#!/bin/bash echo "Hello World!"
Because we are going to start the script by just typing ‘hello’ in the terminal, let’s examine the PATH variable of user joe:
Thus, let’s copy the hello file to /home/joe/.local/bin.
2.1. Scheduling the Job
We are going to run the hello script every minute by means of the cron utility, with an entry in the crontab:
* * * * * hello >> /tmp/hello_output 2>&1
Construct 2>&1 redirects error messages into the standard output. As the latter is redirected into the /tmp/hello_output file, we can easily debug the script.
Now let’s wait and check the output file. The result is different from our expectations. Instead of ‘Hello World’, we find an error message:
/bin/sh: 1: hello: not found
The reason for the failure is that cron doesn’t know about the /home/joe/.local/bin folder. Consequently, it can’t find the script.
Let’s print the PATH of the cron environment by scheduling another job:
* * * * * echo $PATH >> /tmp/path_output
and take a look at the output:
It’s clear that with PATH=/usr/bin:/bin, cron easily finds the echo command but not the hello script.
The cron utility runs commands in a shell, which has the environmental variable PATH different from this one, which is defined in the user’s shell.
3. Passing PATH to the Cron Job
Let’s look through ways to provide the PATH variable to the cron shell.
3.1. Defining the PATH Variable in the Crontab
The crontab -e command allows not only to define jobs but also to set variables of the environment of cron.
We should define variables before any entry for jobs. Furthermore, such a variable affects all jobs of the user’s crontab.
Let’s improve our example and check PATH:
PATH=/usr/bin:/bin:/home/joe/.local/bin/ * * * * * echo $PATH >> /tmp/path_output
After that, we find the correct path with the user’s local bin folder. By the same token, the hello script works now flawlessly.
This approach possesses shortcomings we should be aware of.
Let’s notice that we type the whole path, both the system-wide and local parts explicitly, without using a common idiom PATH=$PATH:/home/joe/.local/bin/, because some implementations of cron do not expand bash variables, denoted with the dollar sign $.
Therefore we would end up with PATH as a plain text $PATH:/home/joe/.local/bin.
As a result, many Linux commands located in /usr/bin or /bin would be unavailable for our script with possibly catastrophic effects.
The other flaw is that some cron implementations don’t allow defining variables in crontab at all.
3.2. Defining the PATH Variable as a Part of the Job
Instead of setting the variable in the crontab, let’s define the PATH variable together with a call to our hello script:
* * * * * export PATH=$PATH:/home/joe/.local/bin/; hello >> /tmp/hello_output 2>&1
In such a case, the bash shell invoked to run the job is responsible for expanding the cron PATH variable, which is present on the right side of the assignment.
Of course, the explicit form of the path is applicable too.
With this approach, each crontab entry may have its own PATH defined separately from each other.
3.3. The PATH Variable From Configuration Files
The more flexible way to deal with PATH and other environmental variables is defining them in a file or reusing the users’ and system settings.
For a comprehensive description of these methods, please read our tutorial on how to load environment variables in a cron job.
In this article, we studied a simple example of a cron job and learned how to pass the PATH environmental variable to a scheduled process.