crontab: schedule recurring jobs
The cron daemon runs commands on a schedule: every night, every Monday, every five minutes. Each user has a crontab, a table of jobs, edited with the crontab command.
crontab -e # edit your crontab
crontab -l # list it
crontab -r # remove it (careful: no confirmation)
crontab -u user -e # as root: edit another user's crontab
The five time fields
# ┌───────── minute (0-59)
# │ ┌─────── hour (0-23)
# │ │ ┌───── day of month (1-31)
# │ │ │ ┌─── month (1-12)
# │ │ │ │ ┌─ day of week (0-7, 0 and 7 = Sunday)
# │ │ │ │ │
* * * * * command to run
| Schedule | Meaning |
|---|---|
30 2 * * * | Every day at 02:30 |
*/5 * * * * | Every 5 minutes |
0 * * * * | Every hour, on the hour |
0 9 * * 1-5 | 09:00 Monday to Friday |
0 0 1 * * | Midnight on the first of every month |
15 3 * * 0 | 03:15 every Sunday |
0 8,12,17 * * * | 08:00, 12:00 and 17:00 |
@reboot | Once at start-up |
@daily, @weekly, @monthly | Shortcuts (Vixie cron, cronie) |
If both day of month and day of week are set, the job runs when either matches. Times are in the system's time zone.
Example crontab
MAILTO=admin@example.com
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# nightly database dump
30 2 * * * /usr/local/bin/db-backup.sh >> /var/log/db-backup.log 2>&1
# clean temporary uploads older than 7 days, every hour
0 * * * * find /srv/app/tmp -type f -mtime +7 -delete
# renew a report every weekday morning
0 7 * * 1-5 cd /opt/reports && ./build.sh --quiet
Why does my job work in the shell but not in cron?
- PATH: cron runs with a minimal
PATH(often just/usr/bin:/bin). Use full paths to programs, or setPATHat the top of the crontab. - Environment: your
.bashrcand.profileare not read. Set the variables the job needs in the script. - Working directory: jobs start in the home directory.
cdfirst or use absolute paths. - The % sign has a special meaning in crontab lines (newline). Escape it:
date +\%F. - Output: output is e-mailed to the user if mail is set up, otherwise lost. Redirect it to a log file with
>> file 2>&1while debugging. - Shell: cron uses
/bin/sh; bash features fail unless you call a bash script or setSHELL=/bin/bash.
Check whether cron ran the job in the logs: journalctl -u cron (Debian, Ubuntu; -u crond on RHEL), or grep CRON /var/log/syslog where rsyslog is installed.
System cron
/etc/crontaband files in/etc/cron.d/have an extra field, the user to run as:30 2 * * * root /usr/local/bin/backup.sh.- Scripts in
/etc/cron.hourly,cron.daily,cron.weeklyandcron.monthlyrun at those intervals. File names must not contain dots on Debian (run-partsignores them). - Who may use crontab is controlled by
/etc/cron.allowand/etc/cron.deny.
One-off jobs with at
echo "/usr/local/bin/report.sh" | at 23:00
at now + 30 minutes <<< "systemctl restart app"
atq # list pending jobs
atrm 3 # remove job 3
On systemd systems, timers are an alternative to cron with better logging: see systemctl.