Search tools

Developer guides

Cron job not running? 10 common causes and how to fix them

Your crontab looks right and the job still never runs. These are the ten causes behind almost every silent cron failure, in the order worth checking them.

You add a line to your crontab, wait for the time to come round, and nothing happens. No error, no email, no log line you can find. Cron fails quietly, which makes it feel mysterious, but the causes are few and they repeat. Work down this list and you will almost certainly find yours.

First, make cron tell you what happened

Before guessing, capture the output. Cron tries to email whatever a job prints to its owner, and on most servers that mail goes nowhere. Send both output streams to a file instead:

*/5 * * * * /home/deploy/sync.sh >> /tmp/sync.log 2>&1

Wait for the next run and read the file. An error message there turns a guessing game into a single fix. It is also worth checking whether cron tried to run the job at all:

grep CRON /var/log/syslog      # Debian and Ubuntu
journalctl -u cron             # Debian and Ubuntu with systemd
journalctl -u crond            # Red Hat, Fedora, Rocky

If the log shows your command at the right time, cron did its part and the problem is inside the job. If there is no entry, the problem is the schedule or cron itself.

1. The cron service is not running

On a fresh server, a minimal image or a container, cron may not be installed or started. Check with systemctl status cron (the service is called crond on Red Hat based systems) and start it with sudo systemctl enable --now cron. Docker containers usually run a single process and have no cron at all unless you add it.

2. The schedule is not what you think

Paste the expression into the cron expression generator and read the plain English version and the next run times. The classic mistakes are * 5 * * *, which runs every minute of the five o’clock hour instead of once, and setting both day fields, which makes cron run when either one matches rather than both.

3. The server is on a different time zone

Cron follows the machine’s clock, and servers are usually set to UTC. A job written for 9:00 in New York runs at 9:00 UTC, which is 4:00 or 5:00 in the morning there depending on the season. Check the clock with date or timedatectl. The guide to cron time zones covers the fixes.

4. The command is not on cron’s PATH

This is the most common cause of all. Cron runs jobs with a minimal environment, and its PATH is usually just /usr/bin:/bin. A command that works in your terminal because it lives in /usr/local/bin, or comes from a Node, Python or Ruby version manager, is simply not found. Use full paths in the crontab (which node tells you where it is), or set PATH at the top of the crontab:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

5. Environment variables are missing

Cron does not read your .bashrc or .profile, so API keys, database URLs and anything else you export in your shell are not there. Set them in the crontab, load them inside the script, or point the script at an env file using its full path.

6. The script relies on its working directory

Cron starts jobs in the user’s home directory, not in the folder the script lives in. A script that opens config.yml or writes to ./data works when you run it from its own folder and fails under cron. Change directory first, as in cd /srv/app && ./run.sh, or use absolute paths inside the script.

7. The script is not executable, or has the wrong line endings

If the crontab calls a script directly, the script needs execute permission and a first line such as #!/bin/bash. Run chmod +x script.sh, or call it through its interpreter: /bin/bash /path/to/script.sh. A script saved on Windows can also carry Windows line endings, which produce a “bad interpreter” error; dos2unix fixes that. The chmod calculator explains what each permission allows.

8. A percent sign in the command

In a crontab, % is special: cron turns it into a newline and feeds everything after it to the command as input. A command such as date +%Y-%m-%d is cut short and fails. Escape each one with a backslash, date +\%Y-\%m-\%d, or move the command into a script.

9. The last line has no newline

Cron expects every line of a crontab, including the last one, to end with a newline. Depending on the version, a missing one means the last job is ignored or the whole file is rejected. If only the final job never runs, open the crontab with crontab -e, go to the end of the last line and press Enter before saving.

10. You edited the wrong crontab

Every user has a crontab of their own, and root’s is separate from yours. A job added with sudo crontab -e runs as root, while crontab -e runs as you, with different permissions and a different home directory. The system file /etc/crontab and the files in /etc/cron.d/ also need an extra field naming the user, between the schedule and the command; without it the line is rejected. List what is really installed with crontab -l, and sudo crontab -l for root.

Jobs that should run after a reboot

If a job needs to run once when the machine starts, cron has a shortcut for it: @reboot /path/to/script.sh. It fires when the cron service starts, which can be before the network or a database is ready, so a script that depends on them should wait or retry. On systemd machines, a service unit with proper dependencies is often the more reliable choice.

The short version

When a job misbehaves, check in this order: capture the output, confirm cron logged the attempt, check the schedule and the server’s clock, then use full paths and set the working directory. Most problems are gone by the fourth step.

Read next