Shell Scripting and Task Automation with cron and systemd Timers
This domain tests writing reliable non-interactive scripts and scheduling them correctly with cron, at, or systemd timers.
Script hygiene
- Start with
#!/bin/bashandset -euo pipefail: fail on error, on unset variables, and on pipeline failures. - Quote expansions (
"$var","$@"), use[[ ]]for tests,casefor branching,read -rfor input,mktempfor temporary files, andtrapfor cleanup. - Positional parameters:
$#count,$1first argument,$?last exit status. Use absolute paths; cron'sPATHis minimal. - Log deliberately: append to a file with timestamps, or write to stdout so journald captures it for timer-driven services.
cron
- Per-user:
crontab -e,-l,-r,-u user. System-wide:/etc/crontab,/etc/cron.d/, and therun-partsdirectories/etc/cron.{hourly,daily,weekly,monthly}. - Fields are minute, hour, day-of-month, month, day-of-week, then the command. A literal
%must be escaped as\%. MAILTO=andSHELL=can be set at the top of a crontab;/etc/cron.allowrestricts who may use cron.
systemd timers
- A
foo.timerunit triggersfoo.service. Key settings:OnCalendar=,OnBootSec=,Persistent=true(run missed jobs after downtime),RandomizedDelaySec=,AccuracySec=. systemctl enable --now foo.timer,systemctl list-timers --all, andsystemd-analyze calendar "Mon..Fri 02:30:00"to validate expressions.athandles one-off jobs:echo /usr/local/bin/job.sh | at now +5 min, thenatqandatrm.
Worked example
Convert the cron line 30 2 * * 1-5 /usr/local/bin/backup.sh into a timer. Use OnCalendar=Mon..Fri 02:30:00 in backup.timer, with Persistent=true so a missed run executes after reboot, and a matching backup.service running ExecStart=/usr/local/bin/backup.sh. Enable the timer, not the service. Reasoning: systemd expresses weekday ranges with .., and enabling the timer is what schedules the service.
Traps
- An unescaped
%in a crontab (date +%F) truncates the command. - Scripts that work interactively fail under cron because of
PATH, environment variables, and missing relative paths. Persistent=trueis required for catch-up runs; without it, missed timers are simply skipped.- A timer unit without its matching service unit does nothing.