Environment Variables in Cron — Complete Guide
In this tutorial, you will learn about Environment Variables in Cron. We cover key concepts, practical examples, and best practices to help you master this topic.
Configure environment variables in cron: PATH, HOME, SHELL, MAILTO, custom variables, debugging environment issues, and ensuring scripts run correctly in cron context.
What You Learn
You will learn how cron handles environment variables, how to set PATH and other variables, common environment-related failures, debugging techniques, and best practices for writing cron-safe scripts.
Why It Matters
The #1 reason Cron Jobs fail is environment differences. Scripts that work perfectly in your terminal fail in cron because PATH is different, HOME is different, and environment variables are missing. Understanding cron's environment is essential.
Real-World Use
DodaTech's deployment scripts failed in cron for weeks. The issue: cron had a minimal PATH that did not include /usr/local/bin where custom tools were installed. Setting PATH at the top of each crontab fixed all failures.
Default Cron Environment
# Cron provides minimal environment by default:
# HOME=/home/username
# LOGNAME=username
# PATH=/usr/bin:/bin
# SHELL=/bin/sh (not /bin/bash!)
# No interactive shell initialization files (.bashrc, .bash_profile)
# Check what environment cron provides:
* * * * * env > /tmp/cron-env.txt 2>&1
# Wait one minute, then:
cat /tmp/cron-env.txt
Setting PATH in Crontab
# Set PATH at the top of your crontab (before any job entries)
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# Now cron jobs can use commands without full paths
0 3 * * * backup.sh # Uses full PATH resolution
# You can also set PATH per job:
0 3 * * * PATH=/custom/bin:$PATH /custom/scripts/deploy.sh
# Common PATH settings for different environments:
# Python virtual environment
PATH=/var/www/venv/bin:/usr/local/bin:/usr/bin:/bin
# Node.js
PATH=/usr/local/node/bin:/usr/bin:/bin
# Docker
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Common Environment Variables
# Set common variables at the top of crontab
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOME=/home/deploy
MAILTO=admin@dodatech.com
LOGNAME=deploy
# Custom application variables
APP_ENV=production
APP_CONFIG=/etc/app/config.yml
DB_HOST=localhost
DB_PORT=5432
LOG_LEVEL=info
# Python-specific
PYTHONPATH=/var/www/app
PYTHONUNBUFFERED=1
# Node.js-specific
NODE_ENV=production
NODE_PATH=/usr/local/node/lib/node_modules
# Now use these in your commands
0 3 * * * /usr/bin/python3 /var/www/app/scripts/backup.py
Debugging Environment Issues
# DEBUGGING TECHNIQUE 1: Dump environment to a file
# Add this temporary cron job:
* * * * * env > /tmp/cron-debug-env.txt 2>&1
# Compare with your terminal environment:
env > /tmp/terminal-env.txt
diff /tmp/terminal-env.txt /tmp/cron-debug-env.txt
# DEBUGGING TECHNIQUE 2: Wrap script with env capture
#!/bin/bash
# /usr/local/bin/cron-wrapper.sh
env > /tmp/cron-env-$(date +%Y%m%d-%H%M%S).txt 2>&1
exec /usr/local/bin/actual-script.sh "$@"
# DEBUGGING TECHNIQUE 3: Check PATH resolution
which python3 # Works in terminal
* * * * * which python3 > /tmp/cron-which.txt 2>&1 # Check in cron
Script with Environment Safety
#!/usr/bin/env python3
"""Cron-safe script that sets up its own environment."""
import os
import sys
import logging
def setup_environment():
"""Ensure critical environment variables are set."""
env_vars = {
'PATH': '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
'HOME': os.path.expanduser('~'),
'LANG': 'en_US.UTF-8',
'LC_ALL': 'en_US.UTF-8',
'PYTHONUNBUFFERED': '1',
}
for key, default in env_vars.items():
if key not in os.environ:
os.environ[key] = default
# Ensure we can find our own modules
script_dir = os.path.dirname(os.path.abspath(__file__))
if script_dir not in sys.path:
sys.path.insert(0, script_dir)
def main():
setup_environment()
logging.basicConfig(level=logging.INFO)
python_path = os.environ.get('PATH', 'not set').split(':')[0]
home = os.environ.get('HOME', 'not set')
logging.info(f"Running with PATH: {python_path}")
logging.info(f"HOME: {home}")
# Actual task logic here
logging.info("Task completed successfully")
if __name__ == '__main__':
main()
Testing Scripts for Cron Compatibility
# Test script as cron would run it:
# Method 1: Use env -i to simulate cron's minimal environment
env -i HOME=/home/user PATH=/usr/bin:/bin SHELL=/bin/sh \
/usr/local/bin/myscript.sh
# Method 2: Run via cron directly (temporary job for testing)
# Add to crontab for one-time test:
* * * * * /usr/local/bin/myscript.sh && crontab -r
# Method 3: Use crontest tool
# pip install crontest
crontest /usr/local/bin/myscript.sh
# Method 4: Shell wrapper that logs environment
#!/bin/bash
# /usr/local/bin/cron-debug.sh
exec >> /var/log/cron-debug.log 2>&1
echo "=== $(date) ==="
echo "PATH=$PATH"
echo "HOME=$HOME"
echo "PWD=$PWD"
echo "---"
exec "$@"
Common Mistakes
1. No PATH Set
Cron's default PATH is /usr/bin:/bin. Commands in /usr/local/bin, /opt, or custom locations are not found. Always set PATH.
2. Relying on .bashrc or .bash_profile
Cron does not source shell initialization files. Environment set in .bashrc is invisible to cron. Set everything in the crontab or the script itself.
3. Using ~ in Cron Jobs
The tilde (~) may not expand to HOME correctly in cron. Use $HOME or the full path instead.
4. Assuming SHELL is Bash
Cron defaults to /bin/sh, which may be dash (Debian/Ubuntu) rather than bash. Use bash-specific features only after setting SHELL=/bin/bash.
5. Hardcoding Paths in Scripts
Scripts that use relative paths fail in cron because the working directory is the user's HOME. Always use absolute paths.
Practice Questions
1. What is cron's default PATH?
/usr/bin:/bin. Commands outside these directories must use full paths or the PATH must be set explicitly.
2. How do you make environment variables available to all cron jobs?
Set them at the top of the crontab file before any job entries. Every job in that crontab inherits them.
3. Why do scripts work in terminal but fail in cron?
Different PATH, missing environment variables, different SHELL, different working directory, and no interactive shell initialization.
4. How do you test if a script is cron-compatible?
Run it with env -i to simulate cron's minimal environment, or add logging to capture the environment at runtime.
Challenge
Write a cron-compatible backup script that: sets its own PATH and HOME, logs all environment variables to a debug file on first run, uses absolute paths for all commands, and sends email on failure with the environment dump attached.
FAQ
Mini Project: Cron Environment Diagnostics
#!/usr/bin/env python3
import os
import sys
import platform
from datetime import datetime
def diagnose_environment():
"""Print diagnostic information about the cron environment."""
print(f"Cron Environment Diagnostic")
print(f"Time: {datetime.now().isoformat()}")
print(f"Host: {platform.node()}")
print()
# Check critical variables
critical_vars = ['PATH', 'HOME', 'SHELL', 'USER', 'LOGNAME', 'PWD', 'LANG']
for var in critical_vars:
value = os.environ.get(var, '*** NOT SET ***')
print(f" {var:10s} = {value}")
print()
# Check if common commands are available
commands = ['python3', 'bash', 'git', 'mysql', 'docker', 'aws']
print(" Command availability:")
for cmd in commands:
path = which(cmd)
status = path if path else 'NOT FOUND'
print(f" {cmd:10s} -> {status}")
def which(cmd):
for dir in os.environ.get('PATH', '').split(':'):
path = os.path.join(dir, cmd)
if os.path.isfile(path) and os.access(path, os.X_OK):
return path
return None
if __name__ == '__main__':
diagnose_environment()
Expected output:
Cron Environment Diagnostic
Time: 2026-06-28T03:00:00
Host: server-01
PATH = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOME = /root
SHELL = /bin/sh
USER = root
LOGNAME = root
PWD = /root
LANG = *** NOT SET ***
Command availability:
python3 -> /usr/bin/python3
bash -> /usr/bin/bash
git -> /usr/bin/git
mysql -> NOT FOUND
What's Next
Now that you understand cron environment variables, explore logging cron jobs for capturing output, then learn about error handling in cron for managing failures.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro