5 poin oleh GN⁺ 19 jam lalu | 1 komentar | Bagikan ke WhatsApp
  • Timer systemd adalah pengganti praktis untuk cron, yang menjalankan unit seperti .service sesuai jadwal serta membuat pengelolaan riwayat, output, dan lingkungan lebih jelas
  • cron tradisional punya beberapa kelemahan praktis: $PATH yang ambigu, stdout/stderr yang mudah hilang, riwayat eksekusi yang sulit dilacak, dan sintaks jadwal yang sulit dibaca
  • Timer menghubungkan .timer dan .service dengan stem yang sama, dan mengekspresikan eksekusi berbasis waktu maupun event melalui OnCalendar, OnBootSec, dan OnUnitActiveSec
  • Dengan systemd-analyze calendar dan systemctl list-timers, Anda bisa memeriksa ekspresi waktu dan waktu eksekusi berikutnya, sementara WakeSystem= dapat membangunkan sistem untuk menjalankan tugas bahkan saat dalam mode suspend
  • RandomizedOffsetSec dan FixedRandomDelay= membantu mengurangi lonjakan eksekusi serentak, dan Persistent= menebus eksekusi yang terlewat saat offline segera setelah sistem kembali online

Alasan memakai timer systemd sebagai pengganti cron

  • Istilah cron job digunakan luas untuk menyebut elemen dasar komputasi yang menjalankan tugas berdasarkan jadwal seperti “jalankan ini setiap hari” atau “jalankan itu setiap bulan”, bahkan bila daemon cron yang sebenarnya tidak dipakai
  • Timer systemd adalah unit systemd yang menjalankan unit lain, biasanya .service, sesuai jadwal tertentu, dan dapat menjadi pengganti fungsional untuk daemon cron tradisional
  • cron tradisional memiliki beberapa kelemahan praktis
    • Konfigurasi $PATH yang ambigu membuat hasil eksekusi skrip sulit diprediksi
    • Output stdout dan stderr sering masuk ke lubang hitam atau dikirim ke sistem mail host
    • Riwayat eksekusi sulit dilacak dan di-query
    • Sintaks jadwal seperti 01,31 04,05 1-15 1,6 * tidak mudah dibaca atau intuitif bagi manusia
  • Timer systemd mengurangi masalah tersebut sambil tetap menyediakan pengaturan kalender yang mirip dengan gaya ekspresi cron

Struktur dasar: service dan timer

  • Timer systemd memerlukan target eksekusi, dan unit .service secara logis bisa dipandang seperti skrip
  • Sebagai contoh, jika Anda menaruh unit berikut di /etc/systemd/system/roulette.service, Anda akan memasang layanan yang mematikan komputer dengan peluang 1 banding 10
[Unit]
Description=1 in 10 chance to break your chains

[Service]
ExecStart=/usr/bin/env bash -c '[[ $(($RANDOM % 10)) == 0 ]] && systemctl poweroff || echo LIVE ANOTHER DAY'
  • ExecCondition= adalah cara yang lebih terintegrasi untuk mengekspresikan eksekusi bersyarat sebagai opsi layanan systemd, dan menampilkan “apakah ini harus terus dijalankan?” dengan lebih jelas di level unit
[Unit]
Description=1 in 10 chance to break your chains

[Service]
ExecCondition=/run/current-system/sw/bin/bash -c '[[ $(($RANDOM % 10)) == 0 ]]'
ExecStart=/run/current-system/sw/bin/systemctl poweroff
  • Jika kondisi tidak terpenuhi, jurnal akan mencatat pesan yang lebih jelas
May 05 11:05:32 diesel systemd[3117]: Condition check resulted in 1 in 10 chance to break your chains being skipped.
  • Secara umum, memanfaatkan opsi yang disediakan systemd memberi pengalaman yang lebih baik daripada menulis skrip sendiri
    • OnFailure= dapat dipakai saat ingin merespons kegagalan skrip layanan
    • Restart= dapat dipakai saat ingin mencoba pulih dari kegagalan sementara

Menghubungkan dan menjalankan unit timer

  • Jika Anda menaruh /etc/systemd/system/roulette.timer dengan stem file yang sama, Anda bisa menghubungkan timer ke roulette.service
[Unit]
Description=impending destruction

[Timer]
OnCalendar=10:00

[Install]
WantedBy=timers.target
  • Secara default, pengaturan Unit= pada timer akan memilih unit layanan dengan .service yang ditambahkan ke stem yang sama
    • Dalam contoh ini, yang dipilih adalah roulette.service
    • Jika ingin menjalankan unit layanan dengan nama lain, Anda bisa mengubah Unit=
  • Target ExecStart= secara default tidak dijalankan sebagai perintah shell
    • Target dengan path absolut harus diperlakukan sebagai skrip, atau sebagai interpreter yang mengharapkan skrip dalam argumen string
    • ExecStart=/usr/bin/echo Hello | /usr/bin/awk tidak akan bekerja di konteks ini karena pipe tidak bermakna
  • Argumen ExecStart= secara default tidak mewarisi variabel lingkungan selain beberapa default dari system manager
    • $PATH default nyaris kosong
    • Menjalankan /usr/bin/env menjadi perlindungan sederhana agar item seperti systemctl dapat digunakan
    • Jika hanya menulis ExecStart=/usr/bin/bash, $PATH akan berisi item default, tetapi memakai env adalah pengaman tambahan
  • Layanan bisa dijalankan langsung tanpa timer
systemctl start roulette
  • Layanan tanpa bagian [Install] tidak bisa di-enable, dan dalam struktur ini timer adalah cara standar untuk menjalankan layanan secara konsisten
  • systemctl secara default bekerja pada roulette.service meski akhiran tidak ditulis eksplisit
  • Menerapkan systemctl start pada unit .timer membuat timer menjadi aktif, tetapi tidak langsung menjalankan layanan target Unit=
systemctl start roulette.timer
  • status akan menunjukkan kapan timer akan dijalankan berikutnya
systemctl status roulette.timer
Trigger: Sat 2026-04-18 10:00:00 MDT; 35min left
  • Alur paling sederhana adalah membuat layanan target eksekusi, menaruh timer dengan jadwal di lokasi yang sama, lalu memulai timer, bukan targetnya
  • Jika [Install] pada unit timer memiliki WantedBy=, timer juga bisa dijalankan saat boot
systemctl enable roulette.timer

Ekspresi waktu: event kalender dan durasi

  • Dalam timer, cara mengekspresikan jadwal itu penting, dan perlu dibedakan antara rentang waktu berulang dengan event kalender atau stempel waktu
  • Manual systemd.time(7) punya cukup banyak contoh dan layak jadi referensi pertama saat menulis timer
  • systemd-analyze dapat memvalidasi dan menjelaskan ekspresi waktu
systemd-analyze calendar '*-*-* *:*:*'
Normalized form: *-*-* *:*:*
    Next elapse: Sat 2026-04-18 16:44:26 MDT
       (in UTC): Sat 2026-04-18 22:44:26 UTC
       From now: 431ms left
  • Timer systemd tidak hanya bisa mendefinisikan waktu berulang berbasis jam dinding, tetapi juga, tidak seperti cron tradisional, durasi berulang yang dihitung dari event sebelumnya
  • Bentuk lengkap daily berarti dijalankan setiap tahun, setiap bulan, setiap hari pada pukul 00:00:00
*-*-* 00:00:00
│ │ │ │  │  ╰── at second 00
│ │ │ │  ╰───── at minute 00
│ │ │ ╰──────── at hour 00
│ │ ╰────────── every day
│ ╰──────────── every month
╰────────────── every year
  • Anda bisa memakai singkatan seperti daily, bentuk lengkap, atau nilai lain yang didukung systemd.time(7), lalu memverifikasi asumsi dengan systemd-analyze

Saat eksekusi berbasis event lebih cocok

  • Dalam pekerjaan nyata, sering kali “jalankan setelah event lain” lebih cocok daripada “jalankan pada jam yang sama setiap hari”
  • Pekerjaan membersihkan direktori sementara mungkin hampir tidak punya apa pun untuk dibersihkan di /tmp jika ekspresi cron untuk sesaat setelah boot sudah terlewat
  • Mengekspresikannya sebagai “jalankan satu jam setelah komputer mulai, lalu setiap satu jam setelah itu” lebih sesuai dengan perilaku layanan yang sebenarnya dan logika penjadwalannya
[Timer]
OnBootSec=1h
OnUnitActiveSec=1h
  • OnBootSec=1h berarti dijalankan sekali satu jam setelah mesin menyala
  • OnUnitActiveSec=1h berarti dijalankan lagi satu jam setelah Unit= dieksekusi, sehingga timer secara implisit terus berulang
  • Ekspresi durasi periodik seperti ini lebih sering cocok untuk penggunaan “jalankan sesekali” daripada ekspresi seperti “jalankan pada menit ini setiap jam”
  • Dalam contoh bot Slack yang melakukan polling API Advent of Code, ekspresi cron */15 memang mematuhi kebijakan API “setiap 15 menit”, tetapi jika semua orang melakukan polling dengan cara yang sama, lalu lintas bisa menumpuk
  • Jika timer dimulai setelah perubahan kode lalu dijalankan setiap 15 menit sesudahnya, perilaku yang dibutuhkan tetap terpenuhi sambil berpotensi mengurangi masalah thundering herd

Melihat status timer secara sekilas

  • systemctl list-timers adalah perintah tingkat tinggi yang merangkum kondisi timer pada sebuah mesin
systemctl list-timers
NEXT                                 LEFT LAST                                  PASSED UNIT                         ACTIVATES
Mon 2026-04-20 15:15:00 MDT      1min 40s Mon 2026-04-20 15:00:05 MDT        13min ago zfs-snapshot-frequent.timer  zfs-snapshot-frequent.service
Mon 2026-04-20 15:32:16 MDT         18min Mon 2026-04-20 14:22:15 MDT        51min ago fwupd-refresh.timer          fwupd-refresh.service
Mon 2026-04-20 16:00:00 MDT         46min Mon 2026-04-20 15:00:05 MDT        13min ago logrotate.timer              logrotate.service
Mon 2026-04-20 16:00:00 MDT         46min Mon 2026-04-20 15:00:05 MDT        13min ago zfs-snapshot-hourly.timer    zfs-snapshot-hourly.service
Tue 2026-04-21 00:00:00 MDT            8h Mon 2026-04-20 09:43:22 MDT     5h 29min ago zfs-snapshot-daily.timer     zfs-snapshot-daily.service
Tue 2026-04-21 07:31:28 MDT           16h Sun 2026-04-19 20:15:47 MDT           7h ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service
Mon 2026-04-27 00:00:00 MDT        6 days Mon 2026-04-20 09:43:22 MDT     5h 29min ago zfs-snapshot-weekly.timer    zfs-snapshot-weekly.service
Mon 2026-04-27 01:09:27 MDT        6 days Mon 2026-04-20 09:43:22 MDT     5h 29min ago fstrim.timer                 fstrim.service
Mon 2026-04-27 04:28:38 MDT        6 days Mon 2026-04-20 09:43:22 MDT     5h 29min ago zpool-trim.timer             zpool-trim.service
Fri 2026-05-01 00:00:00 MDT 1 week 3 days Wed 2026-04-01 10:07:51 MDT 1 week 1 day ago zfs-snapshot-monthly.timer   zfs-snapshot-monthly.service
Fri 2026-05-01 03:17:17 MDT 1 week 3 days Wed 2026-04-01 10:07:51 MDT 1 week 1 day ago zfs-scrub.timer              zfs-scrub.service

11 timers listed.
Pass --all to see loaded but inactive timers, too.
  • Dengan satu perintah, Anda bisa mendapatkan gambaran menyeluruh tentang item-item yang dijalankan menurut jadwal timer
  • list-timers adalah bagian dari keluarga subperintah systemd yang sering dipakai
    • list-units juga berguna
    • list-paths adalah subperintah yang lebih baru ditambahkan ke systemctl

Bangunkan sistem dari mode suspend untuk menjalankan tugas

  • WakeSystem= dapat membuat timer yang waktunya tiba membangunkan sistem dari mode suspend
WakeSystem=
    Takes a boolean argument. If true, an elapsing timer will
    cause the system to resume from suspend, should it be
    suspended and if the system supports this.
...
  • Fitur ini berguna saat skrip penting perlu dijalankan tanpa harus menunggu tindakan fisik seseorang membuka tutup laptop
  • Pada distribusi seperti Arch atau NixOS yang mendukung pengunduhan pembaruan paket sebelum dipakai, Anda bisa mengambil paket pembaruan larut malam dan melakukan pembaruan saat pagi hari sudah berada di depan keyboard
  • Manual menyebutkan bahwa jika ingin kembali masuk mode suspend setelah .service selesai, Anda harus menangani suspend ulang itu secara manual

Menyebarkan waktu eksekusi dan meredam thundering herd

  • Masalah thundering herd adalah masalah sistem yang terjadi saat banyak proses bangun pada saat yang sama
  • Jika semua sistem Debian di seluruh dunia di-hardcode untuk menjalankan apt update pada 00:00:00, tengah malam akan menjadi puncak trafik yang buruk bagi semua orang
  • FixedRandomDelay= dan RandomizedOffsetSec= membantu menyebarkan waktu eksekusi
FixedRandomDelay=
    Takes a boolean argument. When enabled, the randomized delay
    specified by RandomizedDelaySec= is chosen deterministically,
    and remains stable between all firings of the same timer,
    even if the manager is restarted. ...

RandomizedOffsetSec=
    Offsets the timer by a stable, randomly-selected, and evenly
    distributed amount of time between 0 and the specified time
    value. ...
  • Pengaturan seperti ini bisa dipakai pada sistem nyata yang memeriksa pembaruan perangkat lunak
  • Menyebarkan eksekusi secara merata membantu mengurangi masalah thundering herd, membuat perilaku lebih konsisten, dan membantu menghindari gangguan seperti restart daemon yang sedang mengoordinasikan layanan terdistribusi
  • Opsi timing secara umum sangat bisa dikonfigurasi dan memberi kontrol yang rinci

Segera menebus eksekusi yang terlewat

  • Persistent= sangat cocok terutama untuk skrip terjadwal yang tidak boleh terlewat hanya karena laptop sedang suspend, tetapi juga tidak sampai memerlukan WakeSystem=
Persistent=
    Takes a boolean argument. If true, the time when the service
    unit was last triggered is stored on disk. When the timer is
    activated, the service unit is triggered immediately if it
    would have been triggered at least once during the time when
    the timer was inactive. ...
  • Jika sistem yang menjadwalkan check-in manajemen konfigurasi mengalami downtime, cukup menaruh Persistent= pada .timer dapat membuatnya kembali menuju keadaan yang benar segera setelah online
  • Tanpa Persistent=, Anda mungkin harus menunggu sampai waktu eksekusi normal timer berikutnya, dan itu bisa memakan waktu lama
  • Pekerjaan lain yang juga tidak boleh menunggu saat aktivasi terlewat terdeteksi antara lain pembaruan sistem dan pemeriksaan batch job

Hal yang perlu diperhatikan saat menulis timer

  • Timer dalam konteks user manager yang dikelola dengan systemctl --user juga valid, tetapi perhatikan target yang dipakai di [Install]
  • Bergantung pada distribusinya, target yang tepat untuk timer pengguna bisa jadi default.target
  • Seperti pada cron, catatan umum bahwa jam sistem harus akurat tetap berlaku
  • Pengguna systemd dapat memeriksa status sinkronisasi dengan timedatectl timesync-status
  • Banyak editor sudah mendukung format file unit systemd secara bawaan, yang membantu saat file unit mulai membesar
  • Di Emacs, Anda bisa memakai paket emacs systemd

1 komentar

 
GN⁺ 19 jam lalu
Opini Lobste.rs
  • systemd memang tidak sempurna, tetapi terasa banyak keputusan desainnya didasarkan pada pelajaran yang didapat dari cara-cara lama yang lebih tradisional
    Baru-baru ini saya mendengarkan lagi episode CRE tahun 2015 di mana Lennart Poettering menjelaskan latar belakangnya, dan itu masih layak direkomendasikan sampai sekarang

  • Saya termasuk pihak yang benar-benar tidak suka systemd, tetapi systemd.timers menurut saya adalah salah satu konsep yang “lumayan lebih baik” dalam produk ini
    Karena itu, agak mengejutkan melihat penulis membelanya dengan cara yang terkesan meremehkan orang-orang yang punya keluhan yang masuk akal
    Meski begitu, saya suka memakainya bersama perintah at. Untuk perintah yang dijalankan sekali pada waktu tertentu, pakai at, selain itu pakai timer systemd dan unit file sederhana
    Peningkatan yang paling ingin saya lihat adalah kemampuan mengetahui pengguna mana yang sedang menjalankan timer. Saya memang salah satu dari sedikit orang yang masih mengelola shellbox pada 2026, tetapi akan berguna jika saya bisa tahu pengguna mana yang membuat timer yang mengakses disk setiap detik

    • Untuk tujuan ini, mungkin bisa memakai unit pengguna alih-alih membuat semua orang memasang timer sistem
      Setahu saya, dengan loginctl enable-linger, itu bisa berjalan bahkan tanpa sesi pengguna yang aktif. Tentu saja ada kasus penggunaan yang mungkin tidak cukup ditangani dengan itu, dan saya tidak tahu situasi spesifiknya
  • Akan lebih baik kalau systemd timer punya hambatan awal yang lebih rendah, terutama di sisi pengelolaan pengguna
    Kalau melihat jumlah konfigurasi yang dibutuhkan, sangat sulit mengalahkan crontab -e

    • Pendekatan systemd yang membutuhkan beberapa file konfigurasi dan layanan untuk menyiapkan satu timer itu… sebagai pilihan API rasanya benar-benar tidak masuk akal
  • Saya sudah lama memikirkan cara mengumpulkan log skrip cron secara terstruktur, lalu sadar bahwa saya bisa langsung memakai systemd timer
    Masalah logging pun selesai. Sekarang tidak ada alasan untuk kembali memakai cron, dan saya berharap tahu ini lebih cepat

    • Bukankah bisa dipipe ke logger, atau ditambahkan ke file log dengan >>, atau dibiarkan default lalu menerima email?
  • Silakan bilang ini kuno, tapi saya masih menyiapkan email dari server untuk sampai ke saya
    Kalau diotomatisasi, itu ikut tersedia gratis di setiap host baru, dan dalam penggunaan sehari-hari juga cukup nyaman
    Misalnya, saya cukup membuka satu multiplexer lalu menjalankan long_running_process | mail root@localhost -s "done $?" dan melupakannya

  • Tulisan yang bagus, dan saya juga punya draf tulisan serupa yang belakangan harus saya rujuk lagi
    Jika Anda seperti saya dan masuk ke lubang kelinci systemd, saya sarankan membuat tautan simbolis untuk unit file dan timer di folder proyek terkait ke /etc/systemd/system/
    Salah satu keluhan saya terhadap systemd adalah distribusi tidak membedakan unit yang dipasang distro dengan unit yang saya tulis sendiri, dan dengan tautan simbolis saya bisa menjaga pemisahan itu sendiri

    • Sebenarnya, yang menangani pembedaan itu adalah path
      Unit sistem/paket/distribusi masuk ke /usr/lib/systemd/system, sedangkan override lokal atau unit lokal masuk ke /etc/systemd/system