Cron vs systemd
Cron is the classic scheduler. systemd timers are the modern default on systemd-based distros. This page explains the real differences you will care about when jobs fail at 03:00.
Quick Summary
- Cron is portable and simple.
- systemd timers provide better logging, missed-run replay, and dependencies.
- If systemd exists, timers are usually the safer default for production jobs.
Feature comparison
| Capability | Cron | systemd timer | Operational impact |
|---|---|---|---|
| Portability | strong | medium | cron works almost everywhere |
| Missed runs | weak | strong | timers can replay missed jobs |
| Logs by default | weak | strong | journald gives a timeline |
| Dependencies | weak | strong | can wait for mounts/network |
| Resource limits | weak | strong | cap CPU/memory/I/O |
| Environment control | weak | strong | explicit PATH, user, env |
| Overlap prevention | manual | easier | still use locks when needed |
Migration example: cron -> timer
The cron entry
cron-backup-entry.txt
15 2 * * * /usr/local/bin/wp-backup-run >>/var/log/wp-backup.log 2>&1
The systemd units
/etc/systemd/system/wp-backup.service
[Unit]
Description=WordPress backup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/wp-backup-run
/etc/systemd/system/wp-backup.timer
[Unit]
Description=Run WordPress backup daily
[Timer]
OnCalendar=*-*-* 02:15:00
Persistent=true
RandomizedDelaySec=5m
[Install]
WantedBy=timers.target
Enable and inspect:
enable-and-check-systemd-timer.sh
sudo systemctl daemon-reload
sudo systemctl enable --now wp-backup.timer
systemctl list-timers --all | rg -n 'wp-backup'
View logs:
view-timer-job-logs.sh
journalctl -u wp-backup.service --since '24 hours ago' --no-pager
When cron is still the right choice
- You are in a non-systemd environment.
- You need maximum portability.
- The job is simple and you already have logging and locking.
Common timer gotchas
- Timers run a service unit; the service defines user, working directory, and environment.
- If you need a specific user, set
User=in the service. - If your job depends on mounts or network, express that in
[Unit]dependencies.
Quick commands you will actually use:
systemd-timer-debug-commands.sh
systemctl list-timers --all | sed -n '1,80p'
systemctl --no-pager --full status wp-backup.timer || true
systemctl --no-pager --full status wp-backup.service || true
# test run now
sudo systemctl start wp-backup.service
Next steps
- Cron basics:
opt/docker-data/apps/docusaurus/site/docs/server/linux-server/11-automation-task-execution/cron.mdx - System clock and timezone:
opt/docker-data/apps/docusaurus/site/docs/server/linux-server/11-automation-task-execution/cron-depends-on-datetimectl.mdx