Home › Linux & macOS Cron Jobs

Linux Cron Jobs

Everything you need to know about cron jobs on Linux and macOS: crontab commands, syntax, log locations, common mistakes and how to debug a job that is not running.

Essential Crontab Commands

Full reference: crontab(5) and cron(8) man pages at man7.org.

CommandWhat it does
crontab -eEdit the current user's crontab. Creates one if it does not exist.
crontab -lList all cron jobs for the current user.
crontab -rRemove all cron jobs for the current user. No confirmation asked - be careful.
crontab -u username -eEdit another user's crontab (requires root).
crontab -u username -lList another user's crontab.
sudo crontab -eEdit root's crontab. For system-level jobs that need elevated permissions.

Cron Expression Syntax

Five fields, in this order. Every field is required. See the crontab(5) man page for the full specification.

* * * * * command_to_run
│ │ │ │ │
│ │ │ │ └── Day of week  (0-6, Sunday=0, or SUN-SAT)
│ │ │ └──── Month        (1-12, or JAN-DEC)
│ │ └────── Day of month (1-31)
│ └──────── Hour         (0-23)
└────────── Minute       (0-59)
ExpressionMeaning
* * * * *Every minute
*/5 * * * *Every 5 minutes
0 * * * *Every hour, on the hour
0 2 * * *Every day at 2:00 AM
0 9 * * 1-5Weekdays at 9:00 AM
0 0 1 * *First day of every month at midnight
@rebootOnce at system startup
@dailyEquivalent to 0 0 * * *

Crontab File Locations

Linux uses several different crontab files depending on the context. See also the cron(8) man page for full details on how these are processed.

LocationPurpose
/var/spool/cron/crontabs/usernamePer-user crontab (edited with crontab -e). Never edit directly.
/etc/crontabSystem-wide crontab. Has an extra field for the username. Edit directly.
/etc/cron.d/Drop-in crontab files. Same format as /etc/crontab. Used by packages.
/etc/cron.hourly/Scripts that run every hour. No cron expression needed - just drop an executable script.
/etc/cron.daily/Scripts that run every day.
/etc/cron.weekly/Scripts that run every week.
/etc/cron.monthly/Scripts that run every month.

Cron Log Location

Where to look when a cron job is not running or producing errors:

Debian / Ubuntu

grep CRON /var/log/syslog
# or
tail -f /var/log/syslog | grep CRON

CentOS / RHEL / Fedora

tail -f /var/log/cron
# or with journald:
journalctl -u crond -f

Log your own output

The system log only shows when cron fires a job, not what the job does. Capture your script's output separately:

0 2 * * * /path/to/script.sh >> /var/log/myjob.log 2>&1

The 2>&1 redirects stderr to the same file. Without it, errors are silently discarded.

Debugging: Why Is My Cron Job Not Running?

1. Check if cron is running

systemctl status cron      # Debian/Ubuntu
systemctl status crond     # CentOS/RHEL

If it is stopped, start it with systemctl start cron.

2. Test the command manually

/usr/bin/php /var/www/script.php

Run the exact command from your crontab in the terminal. If it fails here, it fails in cron too.

3. Check the system log

grep CRON /var/log/syslog | tail -20

This tells you whether cron is actually firing the job. If the job appears in the log but fails, the problem is in your script.

4. Check script permissions

chmod +x /path/to/script.sh
ls -la /path/to/script.sh

The script must be executable by the user whose crontab it is in.

5. Validate the expression

An expression with a typo or wrong field order will never fire. Paste it in the checker:

Open Cron Checker

6. Check timezone

timedatectl
cat /etc/timezone

Cron runs in the system timezone. If your server is in UTC and you scheduled a job at 9 AM, it runs at 9 AM UTC.

Need a more detailed diagnosis? The full troubleshooting guide covers all causes platform by platform:

Cron Job Not Running - Full Guide

Cron Jobs on macOS

macOS includes cron and uses the same 5-field syntax as Linux. Everything in this guide applies to macOS equally - the same crontab -e, crontab -l and expression syntax. The main difference is where the log lives and the existence of launchd as an alternative.

macOS crontab - same commands

crontab -e    # edit your crontab
crontab -l    # list your cron jobs
crontab -r    # remove all your cron jobs

On macOS, crontab -e opens vi by default. Set EDITOR=nano if you prefer nano.

macOS cron log location

log show --predicate 'process == "cron"' \
  --last 1h

macOS does not write to /var/log/syslog like Linux. Use the log command or open Console.app and filter by "cron".

Full disk access on macOS

On macOS Catalina and later, cron jobs that access protected directories (Desktop, Documents, Downloads) require Full Disk Access permission for /usr/sbin/cron. Go to System Settings › Privacy & Security › Full Disk Access and add cron. Without it, the job runs silently but cannot read or write to protected locations.

launchd as an alternative

Apple recommends launchd over cron for scheduled tasks on macOS. It handles system sleep, missed jobs (runs on wake) and integrates better with macOS security. Create a .plist file in ~/Library/LaunchAgents/ and load it with launchctl load. For simple schedules, cron is fine. For anything that needs to run reliably after sleep/wake cycles, use launchd.

Build your cron expression visually

Use the generator to get the expression right, then paste it directly into your crontab.