Load Environment Variables in a Cron Job


Overview

When crontab runs a command, it doesn't read any environment variables from files like ~/.bashrc, ~/.bash_profile, etc. Because cron runs tasks from a non-interactive, non-login shell, it doesn't need an interactive user Some applications require environmental variables to function correctly.

We’ll discuss different methods for loading environmental variables from a crontab.

Setting the BASH_ENV Variable

We can set environment variables for our shell scripts by using the BASH_ENV variable. We set it up so that when we run our jobs, they're executed by a shell script. We can set up our shell so that when we open a new terminal window, we get the right settings for our system. We can use BASH_ENV to run any shell command without having to know its exact name.

We'll add a line to our crontab file that runs /etc/profile before executing the script.

* * * * * BASH_ENV=/etc/profile /home/baeldung/print_envs.sh

Notice, this job runs every minute. Also, let’s write the /home/baeldung/print_envs.sh script to print all environment variables to a temporal file using printenv −

#!/bin/bash
printenv > /tmp/print_envs_result
Now, after setting execution permission to the script with chmod +x /home/tpoint/print_envs.sh, we’ll wait one minute to see the result:
$ wc -l /tmp/print_envs_result
38 /tmp/print_envs_result
$ grep PS1= /tmp/print_envs_result
PS1=\u@\h:\w\$

We can see that the print_envs script loads 38 environment variables. For example, it loads the PS1 value.

You can also use BASH_ENV to run a custom shell command. We can use this for loading multiple files or adding more variables. Let‘s create a shell file called preload.sh which loads four different files: /etc/profile, ~/.bash_profile, ~/.bashrc, and exports another variable.

#!/bin/bash
. /etc/profile
. ~/.bash_profile
. ~/.bashrc
export LEARNING_FROM=tpoint

Now, we’ll modify the crontab file to use /home/tpoint/preload.sh −

* * * * * BASH_ENV=/home/tpoint/preload.sh /home/tpoint/print_envs.sh

After waiting one minute, we get the result −

$ wc -l /tmp/print_envs_result
41 /tmp/print_envs_result
$ grep LEARNING_FROM /tmp/print_envs_result
LEARNING_FROM=tpoint

We've noticed that there are now 41 environment variables. We also have the variable LEARNING_FROM with the default value “tpoint”.

Wrapping The Job With Bash

Let’s suppose we have this crontab file −

* * * * * printenv > /tmp/print_envs_result

Because printenv isn't a shell script, we can't use BSH_ENV to load environment variable values. However, we can use Bash to wrap it up. We do this by prefixing bash -c to the command and wrapping it in double-quoted strings.

We do this by prepending bash -c to the job and enclosing the job inside double-quotes. Bash uses the -c option when reading commands from the arguments passed to the script.

We’ll add bash -c to our script so we can check for the environment variable BASH_ENV.

* * * * * BASH_ENV=/etc/profile bash -c "printenv > /tmp/print_envs_result"

After cron runs the job, we can see printenv loaded all the environment variables from /etc/profile −

$ wc -l /tmp/print_envs_result
38 /tmp/print_envs_result
$ grep PS1= /tmp/print_envs_result
PS1=\u@\h:\w\$

We could add more environment variables if needed or we could create another shell file to include the additional files we want. Now, we have two options. We can load the updated script by setting an environment variable called BASH_ENV. Just as before. Instead, let's move the original job from its current location in the crontabs file to the end of our new shell scripts.

Let’s create a new shell script called /home/tpoint/wrap_printenvs.sh −

#!/bin/bash
. /etc/profile
. ~/.bash_profile
. ~/.bashrc
export LEARNING_FROM=tpoint
 
#now, we run the original job
printenv > /tmp/print_envs_result

And finally, we change the crontab file to run the new script −

* * * * * /home/tpoint/wrap_printenv.sh

Similarly to the previous section, we can see the environment variables in the result −

$ wc -l /tmp/print_envs_result
41 /tmp/print_envs_result
$ grep LEARNING_FROM /tmp/print_envs_result
LEARNING_FROM=tpoint

Running The Job With a Login Shell

To imitate the same sequence when it comes to running crontab entries, we can use an interpreter (e.g. bash) to run the script. When Bash works as a login shell, it reads files like ~/.bash_profile, ~/.bash_login, /etc/profile and ~/.profile. This way, bash shell will load all the startup scripts, loading the environment vars from those file. We should begin the job with bash -l -c and make sure we enclose it in double quotes. The -l parameter is essential when we want the command to be in login (or interactive) mode.

Let's run the printenv command from the previous section with an interactive shell.

* * * * * bash -l -c "printenv > /tmp/print_envs_result"

Because this is still a non interactive terminal, bash doesn't load the ~/.bashrc file. We can overcome this problem if we use BASH_ENV too.

We'll be using it to load ~/.bashrc and the login shell.

* * * * * BASH_ENV=~/.bashrc bash -l -c "printenv > /tmp/print_envs_result"

We now need to let cron run the script and then check whether any environment variable has been set.

$ wc -l /tmp/print_envs_result
41 /tmp/print_envs_result

Setting Each Variable in The Crontab File

We can set variables by using the name=variable syntax before running commands. We must separate multiple variables by spaces if we want to use multiple variables.

We need to set the environment variables for running the print_envs script −

* * * * * LEARNING_FROM=tpoint LANG=es_US /home/tpoint/print_envs.sh

After one minute, we can now see the script load those values into the page −

$ grep -E 'LANG|LEARNING_FROM' /tmp/print_envs_result
LEARNING_FROM=tpoint
LANG=en_US

If we want to set lots of variables, then we’ll end with a very long line of code. If we do so then the cron job may be difficult to understand.

Programs, like Fedora and Arch Linux, provide cron daemon implementations of cron; with these implementations we can define environment variables in the /etc/crontab file for all jobs (including system wide). We write each environmental variable in one line at once, without any jobs in them.

We’ll define LEARNING_ FROM and LANG for all job types −

LEARNING_FROM=tpoint
LANG=es_US
* * * * * /home/baeldung/print_envs.sh

And as we see, the script loads those variables −

$ grep -E 'LANG|LEARNING_FROM' /tmp/print_envs_result
LEARNING_FROM=baeldung
LANG=en_US

Conclusion

We looked at different ways to set environment variable values for a cron job.

We previously explored how the $BASH_ENV environment variable can be used to run a script before the job starts. This setting permits us to include environmental variables from other sources, like /etc/bashrc.

Next, we see that we can wrap a job within another job where we set and load all the environment variables we need before executing the original job.

We've now learned how to set environment variable values individually, writing them directly into the crontabs file.

Updated on: 03-Jan-2023

5K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements