keepcalculator

06 Numbers and Powers

Debug Cron Job Runs Manually Not Scheduled

Card No. 06·51994 · Updated · Standard formula, shown below

If your cron job runs perfectly when you execute it by hand but never fires on schedule, the problem is almost always in the environment, the cron daemon’s configuration, or the way the job is defined. This guide walks you through the most common causes and fixes, from checking the cron service to debugging environment variables and file permissions.

What You’ll Need

  • Access to the server where the cron job is configured (SSH or a terminal).
  • Ability to run commands with sudo or as the user who owns the crontab (to edit system crontabs or check service logs).
  • A basic understanding of the command line and the cron syntax (minute, hour, day, month, weekday).
  • The exact command or script path that the cron job runs.

Step-by-Step

  1. Verify the cron daemon is running. On most Linux systems, run systemctl status cron (or crond on some distros). If it’s not active, start it with sudo systemctl start cron and enable it to start on boot with sudo systemctl enable cron. On macOS, use sudo launchctl list | grep cron.
  2. Check the crontab syntax. Run crontab -l to list your current cron jobs. Look for errors in the time fields. A common mistake is using 24-hour time incorrectly (e.g., 20 * * * * runs at 20 minutes past every hour, not 8 PM). The format is: minute (0-59), hour (0-23), day of month (1-31), month (1-12), day of week (0-7, both 0 and 7 are Sunday). Use crontab -e to edit and fix any issues.
  3. Ensure the cron job is saved correctly. After editing, the crontab file is installed automatically. But if you’re using a system crontab (like /etc/crontab), you must include the user field. For example: * * * * * root /path/to/script.sh. Missing the user field is a classic silent failure.
  4. Test the exact command from the cron environment. Cron runs with a minimal environment (PATH is often just /usr/bin:/bin). Run env -i /bin/sh -c 'your_command' to simulate cron’s environment. If it fails, you need to set the full path to any executables or source your profile in the script.
  5. Check file permissions and ownership. The script must be executable by the user running the cron job. Use chmod +x /path/to/script.sh if needed. Also, the user must have read and execute permission on the script and on any directories in its path. If the script writes to a file, the user needs write permission to that file and its directory.
  6. Look at the cron logs. On most Linux systems, cron logs to /var/log/syslog or /var/log/cron. Search for your job with grep CRON /var/log/syslog. You’ll see lines like CRON[pid]: (user) CMD (command). If you see No MTA installed or Mail errors, that’s just cron trying to email output; disable it by adding >/dev/null 2>&1 to the end of the command.
  7. Check if the job is actually running but failing silently. Add logging to your script: echo "$(date) - running" >> /tmp/cron.log at the start and end. Then run the job manually and compare the log. If the log doesn’t update when scheduled, cron isn’t executing it; if it updates but the script fails, you’ll see the error.
  8. Verify the timezone. Cron uses the system timezone, not your local time. Run date on the server and compare it to your expected schedule. If the server is in UTC and you’re in EST, a job set for 0 9 * * * will run at 9 AM UTC, not 9 AM your time. You can change the timezone in the crontab by adding CRON_TZ=America/New_York at the top (on most systems).
  9. Check if the job is being overwritten or removed. If you have multiple crontabs (e.g., user crontab and system crontab), a job might be defined in one but not the other. Also, some deployment tools or package managers might overwrite your crontab. Check with crontab -l and also look at /etc/cron.d/ and /etc/cron.daily/ etc.
  10. Test with a simple command. Create a test job that runs every minute: * * * * * echo "test" >> /tmp/cron_test.log. Wait a minute and check if the file appears. This isolates whether cron itself is working.

Common Mistakes

  • Using relative paths in the script. If your script uses ./file or data/file, it will fail because cron’s working directory is the user’s home directory, not the script’s directory. Always use absolute paths or cd to the script’s directory at the start: cd /path/to/script && ./script.sh.
  • Forgetting that the script needs to be executable. A script that runs with bash script.sh manually might not run if the shebang line is wrong or the file isn’t executable. Ensure the shebang (#!/bin/bash) is correct and the file has chmod +x.
  • Assuming cron uses your shell’s PATH. Cron uses a minimal PATH. If your script calls python but python is in /usr/local/bin, it won’t be found. Use the full path (/usr/local/bin/python) or set PATH at the top of the crontab: PATH=/usr/local/bin:/usr/bin:/bin.
  • Not escaping percent signs in the command. In a crontab, a % is treated as a newline. If your command uses percent signs (e.g., date +%Y), you must escape them as \% or the command will be truncated.
  • Using a GUI editor that adds a newline at the end. This is usually fine, but if you accidentally save the crontab with a trailing newline in the middle of a command, it can break. Use crontab -e and check the file with cat -A to see hidden characters.

Tips

  • Always redirect output. Add >> /var/log/myjob.log 2>&1 to your cron command to capture both stdout and stderr. This way, if the job fails, you’ll have a log to inspect.
  • Use a wrapper script. Instead of putting a long command directly in crontab, create a script that sets up the environment (PATH, working directory, etc.) and then runs your actual job. This makes debugging much easier.
  • Test with the exact same user. If the cron job runs as root, test it as root with sudo -u root. If it runs as another user, switch to that user with su - username and test there.
  • Check for special characters. If your command contains >, <, or |, they are interpreted by the shell. If you need them literally, escape them or put them inside quotes.
  • Use a tool like crontab.guru to verify your schedule syntax. It’s a quick way to catch mistakes like setting the hour to 24 or the minute to 60.

Troubleshooting

If you’ve followed the steps and the job still doesn’t run, try these advanced checks:

  • Check for SELinux or AppArmor. On some systems, these security modules can block cron from executing certain scripts. Check the audit logs (/var/log/audit/audit.log) or try temporarily disabling SELinux (not recommended for production) to see if it’s the cause.
  • Look for resource limits. Cron jobs might be killed if they exceed memory or CPU limits set in /etc/security/limits.conf or via systemd. Check the system logs for OOM (out of memory) messages.
  • Check if the job is being run but exiting immediately. If your script has a syntax error, it will fail silently. Run the script manually with bash -x script.sh to trace its execution and find errors.
  • Verify that the cron daemon is not in a broken state. Sometimes the cron service gets stuck. Restart it with sudo systemctl restart cron and check the status again.
  • Check for duplicate cron entries. If you have the same job defined in multiple places (e.g., user crontab and /etc/cron.d), they might conflict. List all cron sources: crontab -l, ls /etc/cron.d/, and cat /etc/crontab.
  • Use cronnext to see the next execution time. Some systems have a tool like cronnext or you can use crontab -l | grep 'your_job' and calculate manually. If the next time is in the past, the schedule is wrong.

Frequently Asked Questions

Why does my cron job run manually but not on schedule?

This almost always comes down to environment differences. When you run a command manually, your shell sets up PATH, working directory, and environment variables. Cron runs with a minimal environment, so commands that rely on your shell’s setup will fail. Also, the cron daemon might not be running, or the crontab syntax might be incorrect.

How do I see cron logs?

On most Linux systems, cron logs are in /var/log/syslog or /var/log/cron. Use grep CRON /var/log/syslog to see cron entries. On some systems, you may need to enable cron logging in /etc/rsyslog.conf or /etc/syslog.conf.

What does No MTA installed mean in cron logs?

MTA stands for Mail Transfer Agent. Cron tries to email the output of your job to the user. If no MTA is installed, it logs this error. It’s harmless, but you can suppress it by redirecting all output to a file or /dev/null.

How do I set the timezone for a cron job?

You can set the CRON_TZ variable at the top of your crontab. For example, CRON_TZ=America/New_York. This is supported by most modern cron implementations (Vixie cron, cronie).

Can I run a cron job every second?

No, cron’s minimum resolution is one minute. To run a job more frequently, you need to use a different tool like systemd timers or a loop in a background script.

Why does my cron job run twice?

This can happen if you have the job defined in both the user crontab and a system crontab (like /etc/cron.d). Also, if you have multiple cron daemons running (e.g., both cron and anacron), they might both execute the job. Check all cron sources and remove duplicates.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →