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. A job wrapped by CronitorCLI is still started by cron, so it gets this environment too. The setup is in the cron jobs guide.
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 full path, the shell searches the directories in PATH. If the crontab does not set PATH, Debian and Ubuntu cron uses /usr/bin:/bin. That default does not include your home directory or ., so a command that works in your terminal can be "not found" under cron. The working directory is still your home directory. That is a separate setting from PATH. When you set PATH in the crontab, cron uses it to find the command.
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 works for a single job. Setting MAILTO stops the mail for every job in the file:
MAILTO=""
Alternatively, if you find cron emails useful, use MAILTO to specify the recipient. cronie (Red Hat, Fedora, and cronie installed elsewhere) also accepts MAILFROM as the envelope sender, which makes filtering easier. Debian's cron man page documents MAILTO and does not document MAILFROM. Your host still needs a Message Transfer Agent (MTA) that is configured to send external email.
Compatibility: MAILTO works on Debian, Ubuntu, and cronie. MAILFROM is cronie.
3. SHELL
By default, cron runs commands with sh. Current Debian sets SHELL to /usr/bin/sh. Older packages, and many other systems, use /bin/sh. On Ubuntu those paths are the same shell, dash, when /bin is merged into /usr. Features that work at an interactive bash prompt are not all available. Set SHELL when you need bash, zsh, or another shell:
SHELL=/bin/bash
Compatibility: Works everywhere
4. CRON_TZ
Cron decides when a job is due using the daemon's timezone. On many servers that is UTC. cronie (Red Hat, Fedora, and cronie elsewhere) reads CRON_TZ and uses that zone for the schedule. Log lines are still stamped in the daemon's local zone.
CRON_TZ=America/New_York
Debian and Ubuntu cron do not schedule from CRON_TZ. TZ in the crontab is handed to the job, so date inside the script can show another zone, but cron still starts the job on the system clock. The Debian man page's workaround is to test the time inside the command. Check man 5 crontab on the host before you rely on either name.
Compatibility: CRON_TZ is cronie. On Debian and Ubuntu, TZ changes the job's environment, not the schedule.
5. RANDOM_DELAY
cronie can delay every job in a crontab by a random number of minutes, up to RANDOM_DELAY. Anacron uses the same variable in /etc/anacrontab, not in a user crontab. Debian and Ubuntu cron ignore it.
RANDOM_DELAY=3
Tip: If you want to add a delay to a single job, you can use the sleep command inline. ${RANDOM:0:1} is bash, so set SHELL=/bin/bash above it, or use sleep 30 for a fixed pause that works in sh.
0 0 * * * sleep ${RANDOM:0:1} && /path/to/executable