When running scripts through cron, you might notice they behave differently than when executed manually - even when running as the same user. This happens because cron jobs don't inherit the full user environment that you get in an interactive shell session.
Cron executes commands in a minimal environment. The key differences are:
- No shell initialization files (.bashrc, .profile) are loaded
- Only a basic set of environment variables are set (PATH, HOME, LOGNAME)
- No terminal or display environment variables
Here are several ways to ensure your cron jobs have the environment they need:
1. Source Your Profile
Modify your crontab entry to load the environment first:
0 2 */1 * * . /root/.profile; /aScript >aLog.log 2>&1
2. Environment Variable File
Create an env file and load it in your script:
# In crontab
0 2 */1 * * /aScript >aLog.log 2>&1
# In aScript
#!/bin/bash
source /path/to/env_vars
# Rest of your script
3. System-wide Environment
For system-wide environment variables, add them to /etc/environment:
# /etc/environment
MY_VAR="my_value"
export MY_VAR
To troubleshoot environment issues:
# Add this to your script temporarily
env > /tmp/cron_env.log
Compare this with your interactive environment:
env > /tmp/shell_env.log
diff /tmp/shell_env.log /tmp/cron_env.log
- Always use absolute paths in cron jobs
- Explicitly set critical environment variables in your script
- Consider using a wrapper script that sets up the environment
- For complex environments, use tools like envdir or direnv
Here's a robust wrapper script example:
#!/bin/bash
# cron_wrapper.sh
# Load environment
source /home/user/.profile
# Set additional variables
export PATH="/custom/path:$PATH"
export MY_APP_HOME="/opt/myapp"
# Run the actual script
/path/to/real_script.sh "$@"
Then in crontab:
0 2 */1 * * /path/to/cron_wrapper.sh >aLog.log 2>&1
When you schedule a cron job as root using crontab -e
, you might expect it to run with the same environment variables as when you execute commands manually as root. However, cron jobs start with a minimal environment by default, which often causes scripts to fail or behave differently.
Cron executes commands in a restricted environment. The key differences include:
- No shell initialization files (.bashrc, .bash_profile) are sourced
- Only a minimal set of environment variables are set (PATH=/usr/bin:/bin)
- No user-specific environment variables are loaded
Here are several effective approaches to solve this issue:
1. Source Environment Manually
Modify your cron entry to load the environment first:
0 2 */1 * * . /root/.bash_profile; /aScript >aLog.log 2>&1
2. Use a Wrapper Script
Create a wrapper script that sets up the environment:
#!/bin/bash
# /root/run_with_env.sh
source /root/.bashrc
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
/aScript >aLog.log 2>&1
Then call it from cron:
0 2 */1 * * /root/run_with_env.sh
3. Set Variables in Crontab
Define variables directly in crontab:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
0 2 */1 * * /aScript >aLog.log 2>&1
4. Use System-wide Environment
For system-wide environment variables, add them to /etc/environment
:
MY_VAR="my_value"
- Always test cron jobs by running them manually first
- Use absolute paths in scripts called from cron
- Log environment variables for debugging:
env > /tmp/cron_env.log
- Consider using systemd timers for complex jobs
To diagnose environment issues:
# Compare environments
env > /tmp/manual_env.log
# In crontab:
* * * * * env > /tmp/cron_env.log
diff /tmp/manual_env.log /tmp/cron_env.log
Remember that cron jobs run in a different context than interactive shells, so environment setup requires explicit configuration.