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.
| Command | What it does |
|---|---|
crontab -e | Edit the current user's crontab. Creates one if it does not exist. |
crontab -l | List all cron jobs for the current user. |
crontab -r | Remove all cron jobs for the current user. No confirmation asked - be careful. |
crontab -u username -e | Edit another user's crontab (requires root). |
crontab -u username -l | List another user's crontab. |
sudo crontab -e | Edit 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)
| Expression | Meaning |
|---|---|
* * * * * | Every minute |
*/5 * * * * | Every 5 minutes |
0 * * * * | Every hour, on the hour |
0 2 * * * | Every day at 2:00 AM |
0 9 * * 1-5 | Weekdays at 9:00 AM |
0 0 1 * * | First day of every month at midnight |
@reboot | Once at system startup |
@daily | Equivalent 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.
| Location | Purpose |
|---|---|
/var/spool/cron/crontabs/username | Per-user crontab (edited with crontab -e). Never edit directly. |
/etc/crontab | System-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 Checker6. 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 GuideCron 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.