Crontab environment variables
Cron jobs are started in their own shell, with their own environment, and their own environment variables. This guide will show you how to set the environment variables for your cron jobs directly in your crontab files, including some that control the behavior of Cron itself.
Why your crontab environment variables are missing
When you open your terminal you start an interactive shell, in this example using bash
, your .bashrc
file is automatically invoked. When this script runs, any environment variables it exports are available to every command you run in your terminal session. This method of setting environment variables in your .bashrc
is the most common way that persistent environment variables are set, but your cron jobs do not invoke an interactive shell, and your .bashrc
is not automatically loaded. This is true even if you specify /bin/bash
as your crontab shell.
Cron offers a few possible solutions that we will cover in detail in the next section.
Want alerts if your cron jobs stop working?
Monitor your cron jobs with Cronitor to easily collect output, capture errors and alert you when something goes wrong.
How to set environment variables for your cron jobs
When setting environment variables for your cron jobs, you have several options depending on your specific requirements, including:
- Declaring variables directly in your crontab files.
- Declaring variables as part of your command line.
- Loading variables from a file before executing your command.
1. Declare the variables directly in your crontab
In this example, we are configuring a PATH variable and a custom application variable. When the cron job runs, it will look for example.sh
in the PATH
provided, and when the command is run, its environment will include the PATH
and APP_ENV
variables too. You can set as many different variables as you need for your jobs, and they can go anywhere in your crontab file.
APP_ENV=production
PATH=/root/it/scripts
0 0 * * * example.sh
One advantage of setting these variables directly in your crontab is that they are clear and easy to find. Anybody trying to understand the crontab file down the road will see every variable required by its jobs.
Unlike bash scripts, the "export" keyword is not needed and not allowed.
2. Declare the variables as part of your command
When you run a command on Linux and other "posix" operating systems, environment variables can be declared inline, and this works with crontab too. Here you can see an example where two jobs are getting different values for the same variable.
0 * * * * APP_ENV=production /var/data-analytics/export-to-datalake.py # Every hour
0 0 * * * APP_ENV=staging /var/data-analytics/export-to-datalake.py # Once a day
This is the best way to set environment variables if you need different values in different jobs. (In this example we are only setting one variable, but you can set as many as needed.)
3. Load variables from a file
When you have a lot of environment variables, or if they are centrally controlled by something like Ansible or Consul, you may have them declared directly in a file that you want to re-use everywhere. In this case, you can source
that file directly as part of your command string. Any variables exported in the file will be part of the environment for the job.
0 * * * * source /var/data-analytics/bootstrap.sh ; /var/data-analytics/export-to-datalake.py
Controlling cron behavior with environment variables
Environment variables declared directly in a crontab file are also available to cron itself, and some can be used to control the behavior of Cron as it runs your jobs. Here are 5 variables you can try in your own crontab:
1. PATH
When a command is run without a fully-qualified path, your shell will look for the command in the locations specified by your PATH
variable. If no PATH
is set, the only place checked will be the current working directory. When you set a PATH variable, it will be used by cron itself to locate your scripts/binaries.
PATH="/users/dataproc/bin:/var/data-analytics/bin:/root/it/scripts"
You can add as many locations, usually delimited by a colon, and they will be searched in the order you write them.
Compatibility: Works everywhere
2. MAILTO and MAILFROM
Anything your job writes to stdout
or stderr
is collected by cron and emailed after your job completes. Often this is an annoying source of spam, especially for frequently-run jobs, and the most common advice to stop the email is to ensure your job never writes to stderr or stdout. That technique is will work to stop emails from a single job, but there’s an easier way to prevent cron from ever sending an email: setting a MAILTO
environment variable.
MAILTO=""
Alternatively, if you find cron emails useful, use MAILTO
to specify the recipient email and you can even set a custom "from" address using the MAILFROM
variable for easier mail filtering and handling. Note: your host will need a Message Transfer Agent (MTA) that is configured to send external email.
Compatibility: Works everywhere
3. SHELL
By default, cron uses the classic “dash” shell at /bin/sh
to invoke your commands, and some features that work at an interactive bash prompt are unavailable in dash. You can tell cron to use bash, zsh or any other shell using the SHELL
variable:
SHELL=/bin/bash
Compatibility: Works everywhere
4. CRON_TZ
Cron jobs are run in whatever timezone the system clock is set to. By default this is UTC, but cron jobs are commonly used to perform actions based on wall clock time in different places around the world. By adding a CRON_TZ
declaration in your crontab, you can control the timezone that Cron uses when starting your jobs.
CRON_TZ=America/New_York
Compatibility: Sometimes this is called TZ
. See man 5 crontab
for details.
5. RANDOM_DELAY
Some implementations of cron, including anacron, allow random delay to all of your jobs is to use the RANDOM_DELAY
variable to define the maximum number of minutes to delay.
RANDOM_DELAY=3
Tip: If you want to add a delay to a single job, you can use the sleep command inline
0 0 * * * sleep ${RANDOM:0:1} && /path/to/executable