EDGE CLUSTERS: yt-dl.unixcorn.org (Media Suite) tor.unixcorn.org (Privacy Archive) cloud.unixcorn.org (Homelab Hub) paste.unixcorn.org (Encrypted Paste) unixcorn.org (DevOps Tools)

Cron job not running? How to find the error on Linux

A script runs over SSH. You add it to crontab, wait for the next run, and nothing happens. Before editing the schedule, find out whether cron launched the command at all. That one check tells you where to look next.

Start with the logs

On Ubuntu and Debian systems running systemd, check the cron service and read its recent messages.

systemctl status cron
sudo journalctl -u cron --since '1 hour ago' --no-pager

If your system writes a syslog file, try sudo grep CRON /var/log/syslog | tail -n 30. Look for a CMD entry at the expected time. It shows cron handed the command to a shell. The command may still have failed.

When the job seems to run silently, temporarily add >> "$HOME/my-job.log" 2>&1 to the end of its command. Run it once and read the log. The directory must already exist and be writable by the job's user. Remove or rotate the debug log after you find the problem.

If the service is inactive and this machine is supposed to run cron, start it with sudo systemctl start cron. If there is still no matching CMD line, check the job's owner and schedule first.

Cron never launches the command

The job is in someone else's crontab

crontab -l shows your jobs. sudo crontab -l shows root's. For a service account, use sudo crontab -u appuser -l, replacing appuser with the real account. Check the same account you expect to own the output files.

bad minute, bad username, or appuser: not found

A personal crontab uses five schedule fields followed by the command. In /etc/crontab and /etc/cron.d/, add the username between the schedule and the command. Use the first example in crontab -e and the second in a system crontab.

15 * * * * /home/appuser/bin/report.sh
15 * * * * appuser /home/appuser/bin/report.sh

If you get bad minute, look at the first field of the reported line. Use 0–59, *, or a valid range, list, or step. Save the file with Unix LF line endings and a final newline. For a file under /etc/cron.d/, use a simple name such as report-job, make root its owner, and keep it unwritable by the group and others.

The job runs at the wrong time

5 * * * * means five minutes past each hour. */5 * * * * means every five minutes. Paste the five fields into the crontab visualizer to check the schedule, then check the server clock with timedatectl. Your browser and server can be in different time zones. On Debian's classic cron, setting TZ in the crontab changes the command's environment while scheduling still follows the daemon's time zone.

Cron launches the command and it fails

command not found or No such file or directory

Cron typically starts jobs with /bin/sh and a smaller environment than your login shell. Use command -v python3 on the server to find the interpreter. If the project uses a virtual environment, call its Python directly. Change to the project directory before running a script that reads relative paths.

15 * * * * cd /home/appuser/report && /home/appuser/report/.venv/bin/python report.py >> /home/appuser/report.log 2>&1

Replace these paths with your own. If the script needs Bash features, run it with /bin/bash /path/to/script.sh or give the executable script a Bash shebang. Load any required settings explicitly instead of relying on shell startup files.

Permission denied

Read the path in the error. cannot create /var/log/report.log points to the output file or directory. Move the log to a location the job's user can write to. For an error on the script itself, check the execute bit and access to its parent directories. Run the same command as the cron user to reproduce the error. Use a harmless test invocation if the real job sends messages or changes data.

A command with date breaks when you add it to cron

In a crontab command, an unescaped % splits off input for the command, even inside shell quotes. Write /bin/date +\%F in the crontab itself. Inside a separate shell script, use /bin/date +%F as usual.

No MTA installed, discarding output

Cron tried to mail the command's output and found no mail transport. Capture stdout and stderr in a writable file using the redirection above. The first useful error is often in that output.

Still stuck? Try a one-minute test

Put this temporary line in the same personal crontab as the failing job. Wait across the next minute boundary and check ~/cron-test.log as that user. Remove the test line when you finish.

* * * * * /bin/date >> "$HOME/cron-test.log" 2>&1

If the timestamp appears, cron can run a simple job for that user. Go back to the original schedule, command, and error log. If it doesn't, recheck the service, the account, and whether the edited crontab was saved.

For schedules you can copy and adapt, see the Linux crontab examples.

References for this guide are the Debian crontab file format, Debian cron daemon manual, and the Ubuntu CronHowto.