Back to posts
Post

5 Ways to Fix Cron Jobs That Won't Run – PATH, Env & Mail

Learn how to troubleshoot silent cron failures by checking PATH, environment variables, and mail output with practical commands and real‑world examples.

Linuxcrontroubleshootingenvironment variableslogging

When a cron job disappears without a trace, the first instinct is to check the script itself. In my environment, the silent killer is usually a mismatch between the user’s interactive shell and the minimal environment cron provides. Below I walk through five practical steps I use to uncover why a cron job isn’t running, focusing on PATH, environment variables, and mail output.

1. Verify the PATH cron sees

Cron does not inherit your user’s $PATH. It typically runs with a very limited set like /usr/bin:/bin. If your script calls tools located in /usr/local/bin, /opt/... or even ~/bin, the job will fail with "command not found" and you’ll never see it unless you look for the error.

A quick way to see what cron actually uses is to run a dummy job that prints the environment:

* * * * * /usr/bin/env > /tmp/cron_env_$(date +\%s).txt 2>&1

After a minute, examine the file. You’ll notice the PATH line is short. Fix this by either:

  • Using absolute paths in your script/command (e.g. /usr/local/bin/mytool instead of mytool).
  • Setting PATH at the top of the crontab:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
* * * * * /usr/local/bin/mytool --option

2. Check other environment variables

Besides PATH, cron clears most variables. Things like HOME, LOGNAME, or custom vars you rely on (e.g. AWS_PROXY, JAVA_HOME) may be missing. The same env‑dump trick above reveals what’s present.

If you need specific vars, define them directly in the crontab line or in a wrapper script:

AWS_PROFILE=production
HOME=/home/furkan
* * * * * /usr/local/bin/aws s3 sync /data s3://my-bucket/backup

Alternatively, source a profile file:

* * * * * . /home/furkan/.profile && /usr/local/bin/mytool

Warning: Sourcing .bashrc can load interactive-only settings that break non‑interactive cron; prefer .profile or a dedicated env file.

3. Capture output and mail

By default, cron mails any stdout/stderr to the local mailbox of the user owning the crontab. If mail isn’t configured, you see nothing. First, verify that the system can deliver mail:

echo "test" | mail -s "cron test" $(whoami)

If you get “mail: cannot send message: process exited with error status”, install and configure an MTA (postfix, exim, or ssmtp) or set MAILTO= to an external address:

[email protected]
* * * * * /usr/local/bin/mytool

If you prefer not to rely on mail, redirect output to a log file:

* * * * * /usr/local/bin/mytool >> /var/log/mytool.log 2>&1

Then monitor the log with tail -f. This also helps when the job runs but produces no visible error.

4. Look at system logs for cron errors

Even when mail fails, the cron daemon logs its own attempts. On systemd‑based systems, use journalctl:

journalctl -u cron --since "10 minutes ago"

On older SysVinit systems, check /var/log/syslog or /var/log/cron. Typical entries look like:

CRON[12345]: (furkan) CMD (/usr/local/bin/mytool)
CRON[12345]: (furkan) MAIL (mailed 1 byte of output; but got exit status 1)

If you see “(furkan) CMD (...)” but no further lines, the job started but exited immediately—likely due to missing PATH or env as discussed.

5. Test the job in a cron‑like environment

The most reliable way to reproduce the issue is to run the command with the same environment cron uses. You can simulate it with env -i and a minimal PATH:

env -i PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOME=$HOME /usr/local/bin/mytool

If this fails, you’ve reproduced the cron failure. Adjust the command or wrapper until it succeeds, then copy the working line back to your crontab.

As I mentioned before in my post about Linux high CPU debugging, systematic isolation beats guesswork. Apply the same principle here: change one variable at a time, observe the result, and move on.

By consistently checking PATH, auditing the environment, capturing output, reviewing daemon logs, and testing in a clean env, you’ll turn those silent cron misses into audible, actionable alerts.


Cover image: njn.icon6 · CC0 (Openverse / kamu malı) · https://www.flickr.com/photos/145773616@N02/46414869341