Terug naar de blog

Cron vs systemd-timers: welke moet je kiezen?

11 september 2026

Op een moderne distro geldt: een systemd-timer voor alles wat je zelf beheert, en cron houden voor one-liner-jobs en servers die je niet zelf hebt ingericht. Timers loggen elke run naar de journal, kunnen schema’s inhalen die gemist werden terwijl de machine uit stond, en hangen aan dezelfde unit-files als alles andere op het systeem. Cron wint op beknoptheid — één crontab -e-regel verslaat twee unit-files — en is nog steeds de enige scheduler die gegarandeerd bestaat op minimale containers en exotische Unix-dozen. Het addertje: cron faalt stilletjes. Maakt je job om 3 uur ‘s nachts een fout, dan mailt cron naar een lokale mailbox die niemand leest, terwijl een timer je journalctl -u mytimer.service geeft met de volledige output. Hieronder: de echte verschillen, hoe je beide test, waarom een timer niet triggert, en een beslistabel.

Wat is het verschil tussen cron en een systemd-timer?

Cron is een daemon die een tabel met regels leest — vijf tijdsvelden en een commando — en elk commando draait zodra de klok klopt. Dat is het hele model. Er bestaat geen job als object: geen unit, geen status, geen dependencies, geen eigen logregel.

Een systemd-timer is een unit-file (foo.timer) die een andere unit-file (foo.service) afschiet wanneer zijn schema klopt. De job is een first-class object met start, status, logs en failure-tracking als elke andere service. Scheduling is ofwel kalendergebaseerd (cron-achtig) ofwel monotoon (OnBootSec=15min, wat geen klokverandering kan misleiden).

De praktische gevolgen:

  • Logging: timers loggen stdout/stderr per unit naar de journal; cron mailt hooguit de lokale gebruiker.
  • Gemiste runs: een timer met Persistent=true draait één keer bij het booten als zijn schema gemist werd; cron slaat gewoon over.
  • Dependencies: timers kunnen wachten op network-online.target of mountpoints; cron laat je retry-logica met de hand in het script schrijven.
  • Syntax: cron is één regel; een timer is twee bestanden. Dat is de volledige overschakelkost.

Welke schedule-syntax is makkelijker — crontab of OnCalendar?

Crons vijf velden zijn de compacte incumbent: */15 * * * * is elke 15 minuten en de meeste admins lezen ze in hun slaap. Systemds OnCalendar= is uitgebreider maar strikt expressiever, en systemd-analyze calendar vertelt je de volgende runs voordat je ‘m vastlegt — cron heeft geen dry-run-equivalent.

# Cron: every day at 03:30
30 3 * * * /usr/local/bin/backup.sh

# systemd: the same schedule, verifiable before you save it
systemd-analyze calendar "*-*-* 03:30:00"
# -> Next elapse: Fri 2026-09-11 03:30:00 ...

OnCalendar doet wat cron echt niet schoon kan uitdrukken: Mon..Fri *-*-* 09..17:00:00 (weekdagen, kantoortijden), of *:0/15 met RandomizedDelaySec=10m zodat duizend machines niet op hetzelfde moment tegen een server beukken.

Hoe test ik een systemd-timer zonder te wachten?

Drie commando’s beantwoorden alles. Lijst op wat er gepland staat en wanneer het volgende vuurt, draai de job met de hand precies zoals de timer dat zou doen, en lees dan de logs:

systemctl list-timers --all                 # every timer, next + last run
sudo systemctl start backup.service         # fire the job now, same unit as the timer
journalctl -u backup.service -f             # watch its output live

Let op de scheiding: systemctl start backup.timer zet het schema scherp; de service is de job. Als list-timers je timer toont, systemctl status backup.service groen is en de journal je output laat zien, werkt de hele keten.

Hoe draai ik een cron-job handmatig?

Cron-jobs draaien met een kaalgestroopte omgeving — daarom is ‘werkt in mijn shell, faalt in cron’ een eigen foutengenre. Om cron getrouw na te bootsen, draai je het commando via sh met dezelfde omgeving die cron zou gebruiken:

crontab -l                                  # confirm the exact line
env -i SHELL=/bin/sh PATH=/usr/bin:/bin sh -c '/usr/local/bin/backup.sh'
grep CRON /var/log/syslog | tail            # did cron even fire it? (Debian/Ubuntu)
journalctl -u cron -n 20                    # same, on systemd distros

Die env -i-regel is de eerlijke handmatige test: een kale omgeving met crons standaard-PATH. De meeste stille cron-storingen zijn een kaal PATH of een ongequote % in het commando (cron leest % als een newline), en beide zie je hier onmiddellijk.

Waarom triggert mijn systemd-timer niet?

Vier oorzaken dekken vrijwel elk geval, in deze controleervolgorde:

  1. Service- en timernaam matchen niet. foo.timer vuurt foo.service af — een vertypte OnFailure of een hernoemde unit betekent dat de timer ‘draait’ in het lege. systemctl cat foo.timer laat exact zien waar hij op mikt.
  2. De timer is aangepast maar niet herladen. Na een wijziging in een unit-file: sudo systemctl daemon-reload && sudo systemctl restart foo.timer. Zonder dat staat je nieuwe schema nog niet aan.
  3. Persistent=true zonder de OnCalendar-semantiek die je verwacht — of je kijkt naar systemctl status foo.timer (toont altijd active, ook inactief) in plaats van naar list-timers.
  4. De service die hij afschiet, faalt meteen, waardoor de timer dood lijkt. journalctl -u foo.service --since -1h toont de crash die list-timers verbergt.

En als je toch in de logs graaft: het journalctl cheat sheet behandelt de filters (-u, --since, -f) die dit snel maken.

Cron vs systemd-timers: de beslistabel

cronsystemd-timer
Installatieéén crontab-regeltwee unit-files
Logginglokale mail, meestal ongelezenjournal, per unit
Gemiste run (machine uit)overgeslagendraait één keer met Persistent=true
Dependencies / volgordegeen — DIY in het scriptvolledige unit-dependencies
Willekeurige vertragingDIY met $RANDOMRandomizedDelaySec=
Schema testen / dry-runneesystemd-analyze calendar
Bestaat overalja — containers, BSD’s, embeddedheeft systemd nodig (PID 1)
Userjobs zonder rootcrontab -esystemd --user-units

Vuistregels: een job uitleveren op je eigen systemd-machine → timer. Snelle persoonlijke herinnering of een doos die je niet zelf hebt gebouwd → cron. Alles met dependencies, retries of de behoefte te weten of het überhaupt draaide → altijd timer. Een veelgebruikt patroon is een timer die een onderhoudsjob draait — bijvoorbeeld een nachtelijke rsync backup — waarbij Persistent=true garandeert dat de backup doorgaat, zelfs als de machine op het geplande moment sliep; dat kan cron simpelweg niet bieden.

FAQ

Zijn cron-jobs verouderd op Linux?

Nee — cron is prima voor simpele tijdstriggers. Timers winnen zodra je inhaalruns, dependencies of logs in de journal nodig hebt.

Wat kunnen systemd-timers die cron niet kan?

Persistente timers halen gemiste jobs na downtime alsnog in; cron slaat ze stilletjes over. Timers ketenen ook dependencies en kunnen startvensters randomiseren.

Hoe debug ik een timer die niet draaide?

systemctl list-timers --all toont de laatste en volgende runs; journalctl -u op de timer en zijn service-unit laat zien waarom hij vuurde of faalde.

— mrsaynothing

— mrsaynothing

Veldnotities over AI, Linux en self-hosting.

Bespreek deze post op dev.to dev.to ↗

De volgende how-to per e-mail

Eén e-mail per post. Fix het en ga door.

self-hosted · geen derden · uitschrijven met één klik

wat is dit?

llama.cpp vs Ollama: welke draai je in 2026?

Schrijf je dit met plezier? Dit bouw ik professioneel. huur me in