How to Manually Execute and Debug Cron Jobs with Identical Runtime Environments


3 views

When debugging cron jobs, the fundamental challenge lies in replicating the exact environment variables and user context that cron provides. Cron executes commands under a minimal environment - typically just HOME, LOGNAME, PATH, and SHELL are set. This differs significantly from your interactive shell environment.

The most reliable method is using env -i to start with a clean environment and then set the minimal cron variables:

env -i \
    PATH=/usr/bin:/bin \
    SHELL=/bin/sh \
    HOME=/home/youruser \
    LOGNAME=youruser \
    /path/to/your/script.sh

For more complex cases, capture cron's actual environment by modifying your script temporarily:

#!/bin/bash
# Debugging snippet to capture environment
env > /tmp/cron_environment.txt
# Rest of your script...

Then recreate it with:

set -a
. /tmp/cron_environment.txt
set +a
/path/to/your/script.sh

Combine environment simulation with output redirection for comprehensive testing:

env -i \
    PATH=/usr/bin:/bin \
    SHELL=/bin/sh \
    HOME=/home/youruser \
    LOGNAME=youruser \
    /path/to/your/script.sh > /tmp/cron_debug.log 2>&1

On modern systems with systemd, you can create transient timers for testing:

systemd-run --user --on-calendar="*-*-* *:*:00" --unit=test-cron /path/to/your/script.sh

Then immediately trigger it with:

systemctl --user start test-cron.service

For advanced use cases, consider these specialized tools:

  • cronic: A wrapper that makes cron output more manageable
  • supercronic: A cron-compatible job runner designed for containers
  • anacron: For systems that aren't always running

Here's a full workflow example:

# 1. Create test script
cat <<'EOF' > /tmp/cron_test.sh
#!/bin/bash
echo "Cron test at $(date)" >> /tmp/cron_test.log
env >> /tmp/cron_test_env.log
EOF
chmod +x /tmp/cron_test.sh

# 2. Execute with cron environment
env -i \
    PATH=/usr/bin:/bin \
    SHELL=/bin/sh \
    HOME=$HOME \
    LOGNAME=$(whoami) \
    /tmp/cron_test.sh

# 3. Examine output
cat /tmp/cron_test.log
cat /tmp/cron_test_env.log

Debugging cron jobs can be frustrating because they run in a different environment than your interactive shell. When a script works fine in your terminal but fails under cron, the usual suspects are:

  • Different PATH environment variables
  • Missing environment variables from your shell profile
  • Different working directory
  • Permission issues

The most accurate way to test is to become the cron user with the same environment:

sudo -u your_cron_user -i /path/to/your/script.sh

Or if you need to preserve the exact cron environment:

sudo -u your_cron_user env -i /path/to/your/script.sh

For even more accuracy, you can capture cron's environment first:

* * * * * env > /tmp/cronenv
wait 60 seconds
source /tmp/cronenv && /path/to/your/script.sh

Add these to your script for better debugging:

#!/bin/bash

# Log environment
env > /tmp/myscript_env.log

# Log current directory
echo "PWD: $PWD" >> /tmp/myscript_debug.log

# Redirect all output
exec >> /tmp/myscript_output.log 2>&1

# Your actual script starts here
...

On systemd systems, you can create an isolated environment similar to cron:

systemd-run --user --pty --same-dir --setenv=PATH=/usr/bin:/bin /path/to/your/script.sh

For Python scripts that fail under cron, try:

sudo -u your_cron_user env -i /usr/bin/python /path/to/script.py

Or with full environment:

sudo -u your_cron_user -i /usr/bin/python /path/to/script.py