Kiet Nguyen logo
NotesNotesResumeResume
© 2026 Kiet Nguyen
← All categories

10

Cron & Timers

  • Why cron job silent-failed
  • Read crontab schedule
  • List systemd timers
crontabSystem cron locationsCron environmentCron servicesystemd timersDebug cron

Must-know cold

  • Cron fields: min hour dom mon dow command (5 time fields + command)
  • crontab -l · crontab -e · absolute paths + redirect logs
  • systemctl list-timers --all · systemctl status job.timer
  • Silent failure classics: PATH, % in the command, bashisms (SHELL=/bin/sh), no logging, wrong user
  • Prefer flock to prevent overlap

Cron field reference

Definition: Five time fields (min hour dom mon dow) that schedule when a cron job runs.

*  *  *  *  *  command
│  │  │  │  │
│  │  │  │  └── day of week (0–7; 0 and 7 = Sunday)
│  │  │  └───── month (1–12)
│  │  └──────── day of month (1–31)
│  └─────────── hour (0–23)
└────────────── minute (0–59)
ExpressionMeaning
*every
*/5every 5 units
1,15,30list
1-5range
0 2 * * *daily 02:00
5 2 * * 0Sundays 02:05
0 */6 * * *00:00, 06:00, 12:00, 18:00 (clock hours, not “every 6h from now”)
0 9 1 * *09:00 on day-of-month 1

Special strings (Vixie/cronie): @reboot @hourly @daily (@midnight) @weekly @monthly @yearly (@annually). @reboot runs when cron starts, not necessarily at kernel boot.

Commands

crontab

Definition: Edit, list, or remove the per-user cron schedule table.

OptionArgumentMeaningExample
-l—List current user crontabcrontab -l
-e—Edit crontab in $EDITORcrontab -e
-r—Remove entire crontabDangerous; confirm first
-i—With -r: prompt before removecrontab -ir
-uUSERAct on USER’s crontab (root)sudo crontab -u jenkins -l
-l-u USERList USERsudo crontab -u www-data -l

Flag combos

ComboMeaningExample
sudo crontab -u jenkins -lCI user scheduleAgents
crontab -l > backup.cronBackup before edit
crontab backup.cronInstall from fileRestore

Install from file: crontab /path/to/file replaces the whole crontab.

System cron locations

Definition: System-wide cron drop-ins and run-parts directories under /etc.

PathMeaning
/etc/crontabSystem crontab (has USER column)
/etc/cron.d/*Drop-in snippets (USER column)
/etc/cron.hourlyrun-parts hourly. No dots in names (job OK, job.sh skipped)
/etc/cron.dailyDaily (often via anacron — not a fixed clock time)
/etc/cron.weeklyWeekly (same anacron caveat)
/etc/cron.monthlyMonthly
/var/spool/cron/crontabs/USERUser spool (distro path varies)
/etc/cron.allow / cron.denyWho may use crontab

/etc/crontab line shape: m h dom mon dow USER command — six fields before the command (USER extra).

Cron environment

Definition: How cron jobs get PATH, logging, and flock single-instance guards.

PatternMeaningExample
Absolute pathDon’t rely on PATH/usr/bin/python3 /opt/job.py
RedirectCapture stdout/stderr... >>/var/log/job.log 2>&1
MAILTO=Email output to addressMAILTO=ops@corp at top of crontab
MAILTO=""Disable mailAvoid mail spam
PATH=Set PATH in crontab (default is often just /usr/bin:/bin)PATH=/usr/local/bin:/usr/bin:/bin
SHELL=Shell for jobs (default /bin/sh, not bash)SHELL=/bin/bash
flockSingle instance. Prefer /var/lock or /run/lock over /tmpflock -n /var/lock/job.lock /opt/job.sh
flock optionArgumentMeaningExample
-n—Fail immediately if lock heldNon-blocking skip
-wSECWait up to SEC for lockflock -w 10 ...
-cCMDRun CMD under lockflock -n /tmp/l.lock -c cmd
(none)LOCKFILE CMDRun CMD with lock heldflock /tmp/l.lock cmd

Cron service

Definition: Check/restart the cron daemon and read its logs.

CommandArgumentMeaningExample
systemctl status cron—Debian/Ubuntu service namesystemctl status cron
systemctl status crond—RHEL family namesystemctl status crond
systemctl restart cron—After major changes (rare need)
journalctl -u cron—Service logsjournalctl -u cron -n 50
grep CRON /var/log/syslog—Classic syslog linesUbuntu
journalctl -t CRON—Identifier filter

systemd timers

Definition: systemd calendar or monotonic schedules that start a service (often Type=oneshot, not required).

CommandArgumentMeaningExample
systemctl list-timers—Active timers + next/lastsystemctl list-timers
systemctl list-timers --all—Include inactivesystemctl list-timers --all
systemctl statusUNIT.timerTimer unit statesystemctl status logrotate.timer
systemctl statusUNIT.serviceOneshot service triggeredsystemctl status logrotate.service
systemctl startUNIT.serviceRun job now (manual)sudo systemctl start backup.service
systemctl startUNIT.timerEnable counting (if stopped)
systemctl enable --nowUNIT.timerBoot + start timersudo systemctl enable --now backup.timer
systemctl catUNIT.timerSee OnCalendar etc.systemctl cat backup.timer
systemd-analyze calendarEXPRValidate calendar exprsystemd-analyze calendar '*-*-* 02:05:00'
journalctl -uUNIT.serviceLogs for the jobjournalctl -u backup.service -n 50

Common timer directives

DirectiveArgumentMeaningExample
OnCalendar=exprCalendar scheduleOnCalendar=*-*-* 02:05:00
OnBootSec=timeAfter bootOnBootSec=15min
OnUnitActiveSec=timeAfter the service last started (not when it finished — that is OnUnitInactiveSec=)
Persistent=trueCatch up missed OnCalendar= runs after downtime. No effect on monotonic timersLaptops/agents
RandomizedDelaySec=timeJitter (stampede control)Fleet
Unit=serviceWhich service to runDefault name match

Flag combos

ComboMeaningExample
systemctl list-timers --all | headWhat’s scheduledMorning check
systemctl start foo.serviceManual catch-upDon’t wait for calendar
journalctl -u foo.service --since todayDid it run?

Debug cron

Definition: Checklist for silent cron failures (env, user, locks, logs).

StepCommand / actionNotes
1systemctl status cronDaemon up?
2crontab -l / sudo crontab -u U -lJob still there?
3Check logsjournalctl -u cron / syslog
4env -i HOME="$HOME" PATH=/usr/bin:/bin /bin/sh /path/job.shSparse env + sh, not bash
5Permissions on script + dirsls -l script
6Lock file stuck?fuser /tmp/job.lock
7SELinux/AppArmor only if enforcingAdvanced

Common recipes

GoalCommand
List my croncrontab -l
Edit my croncrontab -e
List jenkins cronsudo crontab -u jenkins -l
Daily 02:05 job line5 2 * * * /opt/job.sh >>/var/log/job.log 2>&1
Every 5 minutes*/5 * * * * /opt/check.sh >>/var/log/check.log 2>&1
Locked single-run*/5 * * * * /usr/bin/flock -n /var/lock/j.lock /opt/job.sh
List timerssystemctl list-timers --all
Run timer’s service nowsudo systemctl start myjob.service
Validate calendarsystemd-analyze calendar 'Mon *-*-* 09:00:00'

Pitfalls

  • PATH is minimal (/usr/bin:/bin) and SHELL is /bin/sh. Bashisms and bare python fail. Use absolute paths or set PATH= / SHELL= in the crontab.
  • % in a cron command is a newline (rest becomes stdin) unless written \%. date +%Y is a classic silent break.
  • Comments are not allowed on the same line as a job.
  • Output with no redirect is mailed to the owner (MAILTO=). Empty MAILTO="" or log to a file. No MTA → output often vanishes.
  • crontab -r deletes all entries. crontab -e as root edits root’s crontab, not /etc/crontab.
  • DOM and DOW both restricted → OR (Vixie/cronie). 0 9 1 * 1 is the 1st or Mondays, not “first Monday.” systemd OnCalendar= is not that OR.
  • User crontab has 5 time fields; /etc/crontab and /etc/cron.d/* insert a USER field. Files in cron.d / cron.daily with a dot in the name are often ignored (run-parts).
  • Debian/Ubuntu cron.daily often goes through anacron — “daily” ≠ 00:00 sharp.
  • DST: the skipped hour never matches; the repeated hour can run twice.
  • Overlapping long jobs without flock pile up. Put lock files in /run/lock or /var/lock, not world-writable /tmp.
  • Enable the .timer, not usually the .service (or the job also starts at boot). AccuracySec= defaults to 1 min, so timers are not second-exact.
  • Persistent= only catches up calendar timers. Check list-timers LAST/NEXT.

For more details, try man <command> in your terminal.

Previous09 Journal & LogsNext11 Resources: Disk, Memory, CPU