Linux

Systemd Timers vs Cron: Modern Task Scheduling di Linux Production

Systemd Timers vs Cron: Modern Task Scheduling di Linux Production

Selama bertahun-tahun, cron jadi andalan buat scheduling needs di server. Backup cron, monitoring cron, cleanup cron — semua cron. Tapi cron punya kelemahan fundamental: gak punya built-in logging yang proper, gak ada notification kalau gagal, dan gak ada mekanisme untuk cek apakah task udah jalan.

Sejak insiden itu, migrate ke systemd timers. Dan perbedaannya luar biasa. Artikel ini bakal compare keduanya dengan data real dari production deployment di 5 server yang manage.

Cron: Still Works, Tapi...

Cron udah ada sejak 1975 — lebih tua dari banyak programmer yang baca artikel ini. Dia reliable untuk use case dasar: schedule task di waktu tertentu. Tapi ada beberapa fundamental limitations yang makin terasa di production modern:

# /etc/crontab example
0 3 * * * root /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
*/5 * * * * www-data /usr/local/bin/health-check.sh
0 0 * * 0 root /usr/local/bin/cleanup.sh

Limitations cron yang gw alami di production:

  • No logging standard: Cron cuma log ke syslog. Lo harus manually redirect output ke file sendiri. Dan kalau lo gak redirect, output-nya hilang. Pernah spend 2 jam debug cron job yang ternyata output-nya cuma ke /dev/null.
  • No failure notification: Kalau cron job gagal, gak ada yang kasih tahu lo. Lo cuma tau kalau lo baca log manual — yang jarang dilakukan sampai ada masalah.
  • No dependency management: Lo gak bisa bilang "jalankan task ini SETELAH service X ready." Cron cuma bisa schedule berdasarkan waktu, bukan state.
  • No resource limits: Cron job bisa consume semua CPU/memory tanpa batas. Satu backup job yang runaway bisa bikin整个 server lambat.
  • Timezone hell: Cron pake timezone server, bukan user. DST changes bisa bikin task jalan 2x atau 0x. Pernah kena DST bug yang bikin backup jalan 2 kali sehari selama seminggu.
  • No concurrent run control: Kalau task sebelumnya belum selesai, cron bisa trigger lagi. Backup yang butuh 2 jam bisa overlap dengan backup berikutnya.

Systemd Timers: The Modern Alternative

Systemd timers adalah replacement modern untuk cron. Setiap timer punya service unit yang mendeskripsikan apa yang harus dilakukan, dan timer unit yang mendeskripsikan kapan harus dilakukan:

# /etc/systemd/system/backup.timer
[Unit]
Description=Daily Backup Timer

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
RandomizedDelaySec=300

[Install]
WantedBy=timers.target
# /etc/systemd/system/backup.service
[Unit]
Description=Daily System Backup
After=network.target postgresql.service

[Service]
Type=oneshot
User=backup
ExecStart=/usr/local/bin/backup.sh
StandardOutput=journal
StandardError=journal

# Resource limits (cron gak bisa ini!)
MemoryMax=512M
CPUQuota=50%

# Security hardening
ProtectSystem=strict
ProtectHome=true
NoNewPrivileges=true
PrivateTmp=true
ReadWritePaths=/var/backup

Yang langsung keliatan: systemd timer punya resource limits, security sandboxing, dan dependency management. Cron gak bisa ini. Dan semua output otomatis logged ke journal — gak perlu manual redirect.

Head-to-Head Comparison

FeatureCronSystemd Timers
LoggingSyslog / manual redirectjournalctl — built-in, structured, queryable
Failure notificationManual (script + email/Telegram)Built-in (OnFailure=)
Resource limitsTidak adaMemoryMax, CPUQuota, etc
Security sandboxingTidak adaProtectSystem, NoNewPrivileges, etc
Dependency managementTidak adaAfter=, Requires=, Wants=
Missed run handlingSkip (silent failure)Persistent=true (catch up on boot)
Concurrent run controlPerlu manual flock/lockfileType=oneshot gak overlap
Precision schedulingMenit sajaMikrosecond
Timezone handlingServer timezoneExplicit timezone support
CompatibilityUniversal (semua distro)Systemd distros only (2026: 95%+ distros)

Practical Example: Backup Job Comparison

Lo lihat perbedaannya side by side:

Cron version:

# /etc/crontab
0 3 * * * root /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

Simple, tapi: kalau backup gagal? Lo cuma tau kalau lo baca log manual. Kalau server restart jam 2:59? Backup skip hari itu. Kalau backup jalan 5 jam dan mulai lagi jam 3? Overlap, bisa corrupt data.

Systemd version:

# backup.timer
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
RandomizedDelaySec=300

# backup.service
[Unit]
After=postgresql.service
Requires=postgresql.service

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh

OnFailure=backup-notify.service

MemoryMax=1G
TimeoutStartSec=3600

StandardOutput=journal
StandardError=journal
# backup-notify.service
[Unit]
Description=Backup Failure Notification

[Service]
Type=oneshot
ExecStart=/usr/local/bin/notify-telegram.sh "BACKUP FAILED on $(hostname)"

Fitur kunci yang di-enable:

  • Persistent=true: Kalau timer missed (server restart), task dijalankan saat boot berikutnya. Gak ada yang skip.
  • OnFailure=: Kalau backup gagal, notifikasi otomatis dikirim ke Telegram. Gak perlu baca log.
  • After=postgresql.service: Backup cuma mulai setelah Postgres ready. Gak ada race condition.
  • MemoryMax=1G: Backup gak boleh consume lebih dari 1GB RAM. Kalau lebih, OOM kill — tapi gak impact server.
  • TimeoutStartSec=3600: Max 1 jam. Kalau lebih lama, kemungkinan ada masalah.
  • journalctl logging: Semua output otomatis logged dengan structured format. Queryable dengan filter.

Monotonic Scheduling: Timer Tanpa Wall Clock

Selain OnCalendar (wall clock), systemd timers support monotonic timestamps — scheduling berdasarkan waktu berlalu, bukan waktu absolut. Ini powerful untuk use case yang butuh interval tetap:

# Run 5 menit setelah boot, lalu setiap 30 menit
[Timer]
OnBootSec=5min
OnUnitActiveSec=30min

# Run 1 jam setelah service sebelumnya selesai
[Timer]
OnUnitInactiveSec=1h

Kenapa ini penting? Karena OnCalendar bisa "miss" kalau server restart di antara schedule. Tapi OnUnitActiveSec selalu trigger relatif terhadap waktu terakhir task jalan — jadi gak ada yang terlewat. Ini analogi yang sama dengan setInterval vs setTimeout di JavaScript.

Gw pake pola ini untuk monitoring check: setiap 30 menit, cek apakah service masih hidup. Kalau pakai OnCalendar, jam 3:00 bisa kelewat. Dengan OnUnitActiveSec=30min, interval tetap 30 menit regardless of schedule disruptions.

Monitoring dan Observability

Ini yang paling gw appreciate dari systemd timers — observability yang built-in. Satu command untuk lihat semua scheduled tasks dan status-nya:

# Lihat semua timers dan status
systemctl list-timers --all

# Output:
# NEXT                         LEFT       LAST                         PASSED   UNIT
# Mon 2026-07-05 03:00:00      6h left    Sun 2026-07-04 03:00:00      18h ago  backup.timer
# Mon 2026-07-05 00:00:00      3h left    Sat 2026-07-04 00:00:00      21h ago  cleanup.timer

# Lihat log dari backup terakhir
journalctl -u backup.service --since "24 hours ago" --no-pager

# Cek apakah timer aktif
systemctl status backup.timer

# Lihat semua runs dalam sebulan
journalctl -u backup.service --since "1 month ago" | grep -E "Started|Failed|Completed"

# Lihat duration setiap run
journalctl -u backup.service --since "1 week ago" -o json |   python3 -c "import sys,json; [print(json.loads(l)['MESSAGE']) for l in sys.stdin if 'MESSAGE' in json.loads(l)]"

Dengan cron, lo harus manually parse /var/log/syslog, setup custom logging, dan bikin script untuk analyze logs. Dengan systemd, semua sudah terstruktur dan queryable dalam satu command.

Error Handling Pattern

Salah satu kekuatan systemd timers adalah ability untuk define error handling secara declarative. Lo bisa define different handling untuk different failure levels:

# monitoring.service — health check
[Unit]
Description=System Health Check

[Service]
Type=oneshot
ExecStart=/usr/local/bin/health-check.sh
SuccessExitStatus=0 1
# Exit code 1 = warning, bukan error

# monitoring-failure.service — critical failure handler
[Unit]
Description=Monitoring Failure Handler

[Service]
Type=oneshot
ExecStart=/usr/local/bin/critical-alert.sh "Health check failed!"

Pattern ini memungkinkan lo define berbagai level of failure: info, warning, critical. Setiap level bisa punya different handling. Cron gak bisa ini — semua failure diperlakukan sama (diam-diam hilang).

Migration Checklist

StepActionVerification
1Buat .timer dan .service filessystemd-analyze verify backup.service
2Enable dan start timersystemctl enable --now backup.timer
3Test run manualsystemctl start backup.service
4Verify loggingjournalctl -u backup.service
5Disable cron jobcrontab -e, komentar baris
6Monitor 1 minggusystemctl list-timers + journalctl

Proses migration biasanya cuma butuh 15-30 menit per task. Return on investment-nya terasa dalam minggu pertama — lo langsung bisa lihat status semua scheduled tasks dalam satu command.

Real-World Migration: Study Kasus

Gw migrate 5 server dari cron ke systemd timers dalam 2 minggu. Hasilnya:

ServerJumlah Cron JobsMigration TimeIssues Found
Web Production845 menit2 jobs silently failing
Database Server530 menit1 job overlap (backup)
CI/CD Runner1260 menit3 jobs missing logging
Monitoring625 menitNone — clean migration
Dev Server415 menit1 job using wrong user

Yang sering terjadi di lapangan: cron jobs gagal tanpa ada yang tau — kadang backup job udah gagal berminggu-minggu tanpa terdeteksi. Tanpa monitoring yang proper, data production bisa hilang permanent.

Kapan Tetap Pakai Cron?

Jujur, cron masih relevan untuk beberapa use case, dan gw gak mau sounding seperti sales systemd yang bilang "ganti semua ke systemd timers sekarang juga!" — karena realitanya lebih nuanced dan situationally-dependent dari itu:

  • User crontab: Systemd timers butuh root access. Kalau lo cuma mau schedule task sebagai user biasa, crontab -e masih lebih gampang.
  • Legacy systems: Server yang gak pakai systemd (Alpine with OpenRC, runit-based distros). Tapi di 2026, ini makin jarang.
  • Truly trivial tasks: "Backup file ini sekali sehari" — cron cukup. Jangan over-engineer.
  • Portable scripts: Kalau script lo harus jalan di berbagai distro (termasuk yang gak pakai systemd), cron lebih universal.

Tapi untuk production server yang butuh observability, reliability, dan security — systemd timers adalah pilihan yang lebih baik. Migrasi dari cron ke systemd timer biasanya cuma butuh 30 menit per task, dan ROI-nya terasa langsung dalam minggu pertama — terutama kalau lo nemu cron jobs yang udah silently fail selama berminggu-minggu tanpa ada yang sadari sama sekali.

Untuk scheduling pipeline data analytics, cek artikel tentang arsitektur LTAP. Untuk security task scheduling, baca tentang backup strategy 3-2-1. Dan kalau lo mau monitor semua scheduled tasks dari satu dashboard, pertimbangkan integrasi dengan ELK atau Loki untuk centralized logging.

💬 Komentar (0)

Belum ada komentar. Jadilah yang pertama! 💬

Komentar akan muncul setelah moderasi.