cron
Installation
SKILL.md
Identity
- Daemon:
cron(Debian/Ubuntu) orcrond(RHEL/Fedora/Arch) - Unit:
cron.service(Debian/Ubuntu) orcrond.service(RHEL/Fedora) - User crontabs:
crontab -e— stored in/var/spool/cron/crontabs/<user> - System crontab:
/etc/crontab— includes a username field; read by cron directly - Drop-in dir:
/etc/cron.d/— same syntax as/etc/crontab(username field required) - Run-parts dirs:
/etc/cron.hourly/,/etc/cron.daily/,/etc/cron.weekly/,/etc/cron.monthly/ - Logs:
journalctl -u cronorjournalctl -u crond; also/var/log/syslog(Debian) or/var/log/cron(RHEL) - Distro install:
apt install cron/dnf install cronie
Key Operations
| Operation | Command |
|---|---|
| List current user's crontab | crontab -l |
| Edit current user's crontab | crontab -e |
| Edit another user's crontab (root) | crontab -u username -e |
| List another user's crontab (root) | crontab -u username -l |
| Remove current user's crontab | crontab -r |
| Remove another user's crontab (root) | crontab -u username -r |
| List all user crontabs (root) | ls /var/spool/cron/crontabs/ |
| View a user's raw crontab file (root) | cat /var/spool/cron/crontabs/username |
| View system crontab | cat /etc/crontab |
| View drop-in jobs | ls /etc/cron.d/ |
| List run-parts scripts (daily) | ls /etc/cron.daily/ |
| Check cron log (systemd) | journalctl -u cron --since today |
| Check cron log (RHEL syslog) | grep CRON /var/log/cron |
| Test a cron expression | Use crontab.guru (see references) |
| Run a run-parts dir manually | run-parts /etc/cron.daily |
| Force immediate run of one script | bash /etc/cron.daily/myscript |
| Check next scheduled execution | systemctl list-timers (if migrated to systemd) |
Expected State
cron.service(orcrond.service) is active and enabled- Each scheduled run produces a syslog entry:
CRON[pid]: (user) CMD (command) - Output not redirected to a file goes to the local mail spool (
/var/mail/user) unlessMAILTO=""is set
Health Checks
systemctl is-active cron || systemctl is-active crond→activejournalctl -u cron -n 20 --no-pager→ recent job entries visible, no permission errorscrontab -l→ lists expected jobs without error
Common Failures
| Symptom | Likely cause | Check/Fix |
|---|---|---|
| Job never runs | PATH not set; command not found | Use absolute paths; add PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin at crontab top |
| Job runs but produces wrong output | Wrong timezone | Set TZ=America/New_York (or correct zone) at crontab top |
| No visible output, nothing in logs | Output goes to mail; mail not configured | Redirect: >> /var/log/myjob.log 2>&1 and set MAILTO="" |
| Script works manually, fails in cron | Minimal environment; missing env vars | Source profile or set all required vars in the crontab header |
Wrong shell behaviour ([[ ]], etc.) |
Default shell is /bin/sh, not bash |
Set SHELL=/bin/bash at crontab top |
/etc/cron.d/ job never runs |
Missing username field | cron.d syntax requires a username: * * * * * root /path/to/cmd |
| Job runs but fails silently | Script not executable or wrong permissions | chmod +x /path/to/script; check script's shebang line |
crontab: installing new crontab then nothing |
File not saved (editor exited with error) | Re-run crontab -e; confirm the file is non-empty with crontab -l |
Pain Points
- PATH is minimal — cron inherits almost no environment. Always use full paths to binaries (
/usr/bin/python3, notpython3). Alternatively, setPATH=at the top of the crontab. - No environment by default — variables like
HOME,USER,LANG,DISPLAYare not set. Scripts that depend on them must set their own or source a profile. - Output goes to mail — all stdout/stderr is mailed to the crontab owner. On most servers mail is unconfigured, so output is silently lost. Always redirect to a log file.
- Weekday 0 and 7 are both Sunday — the DOW field accepts 0–7 where both 0 and 7 represent Sunday.
*/2in the DOW field steps through 0,2,4,6, which skips Sunday (0) but hits Saturday (6) and Sunday-alias (0 mod 2). /etc/cron.d/requires the username field — unlike user crontabs, files in/etc/cron.d/use the same format as/etc/crontaband must include the running user between the schedule and the command. Omitting it causes the field to be silently misinterpreted.run-partsstrips dots from filenames — scripts in/etc/cron.daily/etc. whose names contain dots (e.g.,backup.sh) are silently skipped byrun-partson Debian-based systems. Use names without dots or extensions.crontab -rhas no confirmation — it removes the entire crontab immediately. If you meantcrontab -e, the job is gone. There is no undo; keep backups withcrontab -l > ~/crontab.bak.
References
See references/ for:
crontab.annotated— fully annotated example crontab with all syntax optionsdocs.md— man pages, expression calculator, and systemd timer comparison
Related skills