The essentials

Quick reference

One focused task per row. Jump to the related section for complete, working examples.

UseSyntaxExamples
List personal crontabcrontab -lView examples
Edit personal crontabcrontab -eView examples
Validate a Cronie tablecrontab -T ./app.crontabView examples
Install a reviewed tablecrontab ./app.crontabView examples
Run on weekday mornings15 6 * * 1-5 /usr/local/bin/report-jobView examples
Run every 15 minutes*/15 * * * * /usr/local/bin/health-sampleView examples
Select Cronie timezoneCRON_TZ=UTCView examples
Set a deterministic PATHPATH=/usr/local/bin:/usr/bin:/binView examples
Define a system cron job20 2 * * * backup /usr/local/libexec/app-backupView examples
Prevent overlapping runsflock -n /run/user/1000/report.lock \ /usr/local/bin/report-jobView examples
Queue commands from a fileat -f ./maintenance.sh 02:30 tomorrowView examples
List queued at jobsatqView examples
Inspect an at jobat -c 42View examples
Remove an at jobatrm 42View examples
Queue for low loadbatch -f ./index-rebuild.shView examples
Define a weekly catch-up job7 20 app-weekly /usr/local/libexec/app-weeklyView examples
Validate anacrontabsudo anacron -T -t /etc/anacrontabView examples
Run one due job in foregroundsudo anacron -d -s app-weeklyView examples

cron handles calendar-like recurring schedules, at queues one-time work, and anacron runs day-scale jobs that became due while a machine was unavailable. Treat each scheduler as an unattended execution environment: use absolute paths, least privilege, explicit logging, locking, bounded runtime, and an independently testable script. Syntax and daemon integration differ among Cronie, Debian cron, BusyBox, and distributions, so verify the local manuals and service layout before deployment.

Step by step

Detailed examples

01

Validate and install complete crontabs deliberately

A personal crontab runs as its owner and has five time fields; /etc/crontab and traditional /etc/cron.d files add a user field. Installing a file with crontab replaces the user's whole table, so export or review the current table first. Cronie provides crontab -T for syntax validation, but that flag and filename rules are not portable to every cron implementation. Use crontab rather than editing spool files directly, and confirm the local daemon is enabled under the distribution-specific cron or crond service name.

Review, validate, and install a personal table
crontab -l > ./crontab.before
crontab -T ./app.crontab
crontab ./app.crontab
crontab -l

Note: The install command replaces the complete personal table. The -T validation option is a Cronie extension; check crontab(1) locally.

Back to quick reference ↑
02

Read cron fields as calendar matches, not elapsed intervals

The common five fields are minute, hour, day of month, month, and day of week. Lists, ranges, and steps apply inside a field, so */15 means four fixed minute values rather than 15 minutes after the previous completion. In Vixie-derived cron, restricting both day fields makes them an OR condition: a row can run when either field matches. Cron does not queue one replacement run for every missed minute during an outage, and DST skip or repeat behavior differs by implementation; use an idempotent job and verify the local cron(8) semantics when civil-time precision matters.

Representative personal crontab expressions
# minute hour day-of-month month day-of-week command
15 6 * * 1-5 /usr/local/bin/report-job
*/15 * * * * /usr/local/bin/health-sample
0 3 1 * * /usr/local/bin/month-open
Back to quick reference ↑
03

Make the unattended execution environment explicit

Cron normally invokes /bin/sh unless SHELL says otherwise, and it does not initialize an interactive login environment. Set a minimal PATH, use absolute paths for scripts and data, establish a working directory inside the script, and redirect output to a monitored destination. In Vixie-derived tables, an unescaped percent sign in the command is converted to a newline and the remainder becomes standard input. CRON_TZ is supported by Cronie but is not portable everywhere; cron logs can remain in the daemon's local timezone. Do not put database passwords, tokens, or private keys in a readable crontab or command line—load narrowly permissioned credentials from the job under the service account instead.

Self-contained user crontab
SHELL=/bin/sh
PATH=/usr/local/bin:/usr/bin:/bin
CRON_TZ=UTC
MAILTO=ops@example.com

15 6 * * 1-5 /usr/local/bin/report-job
Back to quick reference ↑
04

Assign the least-privileged identity in system tables

A row under /etc/cron.d or /etc/crontab conventionally contains a username after its five schedule fields, while a user's crontab does not. Mixing the formats silently shifts fields and breaks execution. Root-owned system files should not be writable by the job account, and scripts called by privileged rows must not be writable through an untrusted directory. Package and distribution integrations vary: some use run-parts directories, some use anacron, and others replace these jobs with systemd timers. Inspect installed files rather than assuming one layout.

Root-managed schedule that runs as backup
# /etc/cron.d/app-backup
SHELL=/bin/sh
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=ops@example.com
20 2 * * * backup /usr/local/libexec/app-backup
Back to quick reference ↑
05

Inspect one-time at jobs before their execution time

at reads a script from standard input or -f, queues it, and reports a job identifier. The job later runs without a terminal in a separate shell process; the submission environment, current directory, and umask are generally captured, but open descriptors and interactive state are not. Time grammar, daemon name, queue load threshold, and allow or deny file paths vary across implementations. Use atq and at -c to verify the exact job and environment, redirect useful output, and remove an incorrect job with atrm before it runs.

Prepare and audit a one-time job
sh -n ./maintenance.sh
at -f ./maintenance.sh 02:30 tomorrow
atq
at -c 42

Note: Replace 42 with the identifier printed by at. Submission changes the external queue; the commands are shown for an authorized maintenance window.

Back to quick reference ↑
06

Use anacron for day-scale catch-up, not exact wall-clock timing

Anacron checks date-only timestamp files and runs daily, weekly, or monthly work that is due, making it suitable for machines that are not continuously available. An entry contains period in days, delay in minutes, a unique identifier, and a command. START_HOURS_RANGE constrains starts; if the machine misses that entire window, the job is not run that day. RANDOM_DELAY adds fleet jitter. Test with -T first: -f forces jobs regardless of timestamps, -n discards configured delays, and -u marks jobs current without running them, so all three can materially alter expected processing.

Bound and spread a weekly catch-up job
# /etc/anacrontab
SHELL=/bin/sh
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=ops@example.com
RANDOM_DELAY=30
START_HOURS_RANGE=6-10
7 20 app-weekly /usr/local/libexec/app-weekly
Back to quick reference ↑
07

Design scheduled work for retries, overlap, and outages

A scheduler reporting an activation is not proof that business work completed. Make the script return a nonzero status on failure, record start and success markers, enforce a runtime limit where appropriate, and alert on the age of the last success. Cron may start another copy while the previous run is active; use an identity-scoped lock and decide whether to skip or wait. Anacron locks its own active job identifiers, but external invocations can still overlap. Network-dependent work must tolerate DNS, authentication, and remote outages without promoting partial output or deleting the last good backup.

Lock and log a recurring command
#!/bin/sh
set -eu
log_dir=$HOME/.local/state/report-job
mkdir -p "$log_dir"
exec flock -n "$log_dir/run.lock" /usr/local/bin/report-job >>"$log_dir/job.log" 2>&1

Note: Choose a lock path private to the job identity. A skipped locked run should be visible to monitoring if every occurrence is required.

Back to quick reference ↑

Sources and further reading

References

Authoritative documentation used to verify and expand this cheat sheet.

  1. Cronie Project via man7.orgcrontab(5)man7.org
  2. Cronie Project via man7.orgcrontab(1)man7.org
  3. Cronie Project via man7.orgcron(8)man7.org
  4. The Open Groupat — Execute Commands at a Later Timepubs.opengroup.org
  5. Debian Projectat(1) Manual Sourcesources.debian.org
  6. Cronie Project via man7.organacron(8)man7.org
  7. Cronie Project via man7.organacrontab(5)man7.org

Help us improve

Found a typo or missing example?

Tell us what would make this cheat sheet clearer, more complete, or more useful.

Share feedback