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


13 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