Otomatisasi dengan Cron & Systemd

Otomatisasi dengan Cron & Systemd

Bitnesia • Aug 30, 2026 70 •EN

Studi kasus penutup Bab 17 menghasilkan audit-server.sh, script yang mencetak kondisi server lengkap hanya dengan satu perintah manual. Masalahnya, Sysadmin yang mengelola server produksi jarang punya waktu login setiap pagi cuma untuk menjalankan satu script; kebutuhan sebenarnya adalah script itu berjalan sendiri, tepat waktu, tanpa campur tangan manusia sama sekali. Bab ini membahas dua cara paling umum mewujudkan itu di Linux: cron, penjadwal tugas klasik yang sudah jadi standar de-facto sejak era Unix awal, dan systemd timer, alternatif yang lebih modern dan terintegrasi penuh dengan systemd selaku init system di hampir semua distro Linux kekinian. Pembahasan dimulai dari sintaks crontab dan jebakan environment yang sering bikin bingung pemula, dilanjutkan pengenalan timer unit systemd, cara menjalankan script sebagai service lewat unit file, lalu ditutup studi kasus menjadwalkan ulang script audit dari Bab 17 lewat kedua metode itu sekaligus.

18.1 Penjadwalan Tugas dengan cron dan crontab

Cron adalah daemon penjadwal tugas yang berjalan terus di background sejak sistem menyala, membaca daftar jadwal dari satu atau banyak file crontab, lalu menjalankan perintah yang tercantum di dalamnya persis pada waktu yang ditentukan. Tidak perlu sesi login aktif atau terminal terbuka; cron memang dirancang khusus untuk tugas yang berjalan tanpa kehadiran manusia. Implementasinya sendiri bervariasi antar distro, umumnya cronie di RHEL/Fedora atau paket cron berbasis Vixie cron di Debian/Ubuntu, tapi format crontab yang dibahas di sub-bab ini konsisten di semua implementasi tersebut, sesuai spesifikasi man 5 crontab.

18.1.1 Format dan Sintaks Crontab

Satu baris di dalam crontab terdiri dari lima field jadwal diikuti perintah yang akan dijalankan, dipisah spasi.

* * * * * perintah_yang_dijalankan
FieldRentang NilaiCatatan
Menit0-59-
Jam0-23Format 24 jam
Tanggal (hari dalam bulan)1-31-
Bulan1-12Boleh pakai singkatan nama bulan, misalnya Jan, Dec
Hari dalam minggu0-70 dan 7 sama-sama merujuk hari Minggu; boleh pakai singkatan nama hari, misalnya Mon, Fri

Tanda bintang (*) berarti "setiap nilai yang mungkin" di field itu. Tiga karakter khusus lain memperluas ekspresi jadwal jadi jauh lebih fleksibel: koma (,) untuk daftar nilai, tanda hubung (-) untuk rentang nilai, dan garis miring (/) untuk kelipatan (step).

*/15 * * * * /usr/local/bin/cek-koneksi.sh
0 2 * * * /usr/local/bin/backup-harian.sh
0 9 * * 1-5 /usr/local/bin/laporan-pagi.sh
30 3 1 * * /usr/local/bin/rotasi-log-bulanan.sh

Baris pertama menjalankan cek-koneksi.sh tiap kelipatan 15 menit. Baris kedua menjalankan backup-harian.sh setiap hari pukul 02:00. Baris ketiga menjalankan laporan-pagi.sh pukul 09:00 tapi hanya di hari Senin sampai Jumat (1-5), berguna untuk tugas yang memang cuma relevan di hari kerja. Baris terakhir menjalankan rotasi-log-bulanan.sh pukul 03:30 di tanggal 1 tiap bulan.

Sebagian besar implementasi cron modern, termasuk Vixie cron dan cronie, juga mendukung tujuh kata kunci pintasan yang menggantikan lima field jadwal sekaligus untuk pola yang sangat umum: @reboot (dijalankan sekali setiap cron daemon baru mulai, biasanya berarti setiap sistem baru boot), @yearly atau @annually, @monthly, @weekly, @daily atau @midnight, dan @hourly. Kata kunci ini bukan bagian dari standar POSIX cron, jadi tidak wajib tersedia di semua sistem Unix-like, tapi aman dipakai di praktis semua distro Linux modern.

@daily /usr/local/bin/backup-harian.sh
@reboot /usr/local/bin/mount-disk-tambahan.sh

18.1.2 Mengedit Crontab dengan crontab -e

Setiap user punya crontab miliknya sendiri, dan cara resmi mengeditnya bukan membuka filenya langsung lewat editor teks, melainkan lewat perintah crontab -e.

crontab -e

Perintah ini membuka crontab milik user yang sedang login memakai editor yang ditentukan lewat variabel VISUAL atau EDITOR (jatuh ke editor bawaan sistem, biasanya vi, kalau keduanya tidak di-set). Setelah disimpan, cron otomatis membaca ulang isinya tanpa perlu me-restart daemon-nya secara manual. Untuk melihat isi crontab yang sedang aktif tanpa membukanya untuk diedit, pakai opsi -l.

crontab -l

File crontab tiap user sebenarnya disimpan di sebuah direktori spool khusus yang lokasi persisnya beda antar distro, misalnya /var/spool/cron/crontabs/ di Debian/Ubuntu atau /var/spool/cron/ di RHEL/Fedora. Path ini sengaja disebut sekadar sebagai konteks, bukan ajakan mengeditnya langsung; selalu pakai perintah crontab -e, jangan pernah membuka atau menimpa file di direktori spool itu langsung lewat editor teks biasa. Selain lupa memberi tahu daemon cron soal perubahan, format dan permission file di spool itu juga cukup ketat, dan cron biasanya menolak file yang permission-nya salah demi keamanan.

Root, atau user mana pun yang diberi izin lewat /etc/cron.allow//etc/cron.deny, bisa mengedit crontab milik user lain lewat opsi -u.

sudo crontab -u deploy -e

Satu opsi yang wajib dipakai dengan hati-hati adalah -r, yang menghapus seluruh isi crontab user itu tanpa konfirmasi apa pun di kebanyakan implementasi cron. Biasakan menjalankan crontab -l > backup-crontab.txt lebih dulu sebelum bereksperimen dengan -r, supaya jadwal yang sudah ada tidak hilang begitu saja kalau ternyata perintahnya salah ketik atau salah target user.

18.1.3 Environment dan PATH di Cron

Jebakan paling klasik yang dialami hampir semua orang yang baru pertama kali memakai cron: script yang berjalan mulus saat dites manual dari terminal, tapi gagal total begitu dijadwalkan lewat cron, tanpa pesan error yang jelas. Penyebabnya hampir selalu sama, cron menjalankan setiap perintah dengan environment yang jauh lebih minim dibanding shell interaktif biasa. Cron tidak membaca ~/.bashrc, ~/.bash_profile, atau /etc/profile, karena perintah yang dijalankannya bukan login shell maupun interactive shell seperti dibedakan di Bab 1.4. Akibatnya, alias, function di .bashrc, dan variabel PATH tambahan yang biasa dipakai sehari-hari sama sekali tidak tersedia di dalam konteks cron.

Variabel PATH bawaan cron sendiri jauh lebih pendek dari PATH interaktif biasa, umumnya cuma berisi /usr/bin:/bin, sesuai perilaku default yang didokumentasikan di man 5 crontab. Perintah yang letaknya di luar dua direktori itu, misalnya binary yang dipasang lewat package manager pihak ketiga di /usr/local/bin atau /opt, tidak akan ditemukan kecuali dipanggil dengan path lengkapnya.

0 2 * * * backup-harian.sh
0 2 * * * /usr/local/bin/backup-harian.sh

Baris pertama berisiko gagal dengan pesan seperti command not found kalau backup-harian.sh tidak kebetulan ada di /usr/bin atau /bin. Baris kedua, memakai path absolut, jauh lebih aman dan jadi kebiasaan wajib untuk setiap perintah yang dijadwalkan lewat cron, bukan cuma untuk script itu sendiri tapi juga untuk perintah apa pun yang dipanggil di dalamnya (tar, rsync, curl, dan sejenisnya).

Kalau menuliskan path absolut di setiap baris terasa berulang, PATH juga bisa di-set ulang langsung di baris paling atas crontab, berlaku untuk seluruh baris jadwal di bawahnya.

PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/bin
SHELL=/bin/bash

0 2 * * * backup-harian.sh

Variabel SHELL di atas menentukan shell apa yang dipakai cron untuk menjalankan tiap perintah, default-nya /bin/sh, bukan /bin/bash. Ini penting terutama kalau perintah di crontab memakai sintaks khusus Bash seperti array atau [[ ]] tanpa memanggil script lewat shebang #!/bin/bash-nya sendiri; menuliskan SHELL=/bin/bash secara eksplisit menghilangkan ambiguitas itu.

18.1.4 Output dan Log Cron Job

Secara default, cron tidak membuang output dari perintah yang dijalankannya. Menurut man 5 crontab, stdout dan stderr dari setiap job ditangkap dan dikirim lewat email ke pemilik crontab-nya, memakai Mail Transfer Agent (MTA) lokal seperti sendmail atau postfix. Di lapangan, kebanyakan server modern tidak memasang MTA lokal sama sekali, sehingga email itu gagal terkirim secara diam-diam, tanpa error yang terlihat di mana pun. Sysadmin baru sering mengira job-nya "berjalan tanpa masalah" padahal sebenarnya gagal total dan pesan errornya menghilang begitu saja ke email yang tidak pernah sampai.

Kebiasaan yang jauh lebih andal adalah meredirect output setiap job secara eksplisit ke sebuah file log.

0 2 * * * /usr/local/bin/backup-harian.sh >> /var/log/backup-harian.log 2>&1

Pola >> file 2>&1 ini sama persis dengan yang dibahas di Bab 5.3, menambahkan (append) baik stdout maupun stderr ke satu file log yang sama, tanpa menimpa isi sebelumnya di tiap kali dijalankan. Kalau output memang sengaja tidak dibutuhkan sama sekali, redirect ke /dev/null jauh lebih jelas niatnya dibanding membiarkannya default ke email yang mungkin tidak pernah terkirim.

Variabel MAILTO di baris atas crontab mengendalikan ke mana email itu dikirim kalau memang MTA tersedia dan berfungsi; men-set-nya jadi string kosong menonaktifkan pengiriman email sama sekali, cocok dipasangkan dengan kebiasaan redirect ke file log di atas.

MAILTO=""
0 2 * * * /usr/local/bin/backup-harian.sh >> /var/log/backup-harian.log 2>&1

Output job dan log aktivitas cron itu sendiri adalah dua hal yang berbeda. Cron mencatat kapan setiap job mulai dijalankan (tanpa isi output-nya) ke syslog, bisa dicek lewat journalctl di distro yang memakai systemd-journald.

journalctl -u cron
journalctl -u crond

Nama unit service-nya sendiri beda antar distro, cron di Debian/Ubuntu dan crond di RHEL/Fedora, jadi cek dulu nama yang sesuai lewat systemctl status cron atau systemctl status crond kalau salah satunya tidak ditemukan. Log aktivitas ini berguna untuk memastikan cron benar-benar memicu job pada jadwalnya, terpisah dari urusan apakah job itu sendiri berhasil atau gagal, yang baru terlihat dari isi file log output-nya.

18.1.5 Crontab Sistem dan /etc/cron.d

Semua contoh sejauh ini memakai crontab milik satu user tertentu. Untuk kebutuhan yang berlaku di seluruh sistem, ada juga crontab sistem di /etc/crontab, formatnya mirip tapi menyisipkan satu field tambahan, nama user, tepat setelah lima field jadwal dan sebelum perintahnya. Field tambahan inilah yang membedakannya dari crontab per-user: crontab per-user otomatis tahu job itu milik siapa (pemiliknya sendiri), sedangkan crontab sistem bisa menjalankan job sebagai user mana pun dalam satu file yang sama.

# m h dom mon dow user command
0 3 * * * root /usr/local/bin/backup-sistem.sh

Direktori /etc/cron.d/ menampung file-file terpisah dengan format persis sama seperti /etc/crontab di atas, termasuk field user-nya. Ini cara yang lazim dipakai package manager memasang jadwal cron miliknya sendiri, misalnya paket mysql-server atau certbot, tanpa perlu ikut mengedit satu file /etc/crontab bersama yang berisiko konflik antar paket. Baik Debian/Ubuntu maupun RHEL/CentOS/Fedora sama-sama mendukung mekanisme /etc/cron.d/ ini.

Sebagian besar distro turunan Vixie cron, termasuk Debian/Ubuntu dan RHEL/CentOS, juga menyediakan empat direktori siap pakai: /etc/cron.hourly/, /etc/cron.daily/, /etc/cron.weekly/, dan /etc/cron.monthly/. Taruh script yang sudah diberi izin eksekusi di salah satu direktori itu, dan cron akan menjalankannya sesuai intervalnya tanpa perlu menulis satu baris jadwal pun; mekanismenya lewat entri di /etc/crontab bawaan paket cron yang memanggil run-parts untuk mengeksekusi semua script di dalam direktori itu satu per satu. Jam pasti eksekusinya sendiri bisa berbeda antar distro, jadi jangan berasumsi semua server menjalankan cron.daily di jam yang sama; cek langsung isi /etc/crontab atau konfigurasi anacron di server yang bersangkutan kalau butuh kepastian waktunya.

18.2 Systemd Timer sebagai Alternatif Cron

cron sudah cukup untuk kebutuhan penjadwalan yang sederhana, tapi punya beberapa keterbatasan yang mulai terasa di server yang lebih kompleks: tidak ada catatan log terstruktur bawaan, tidak ada mekanisme "susulan" otomatis kalau server mati tepat saat jadwal seharusnya jalan, dan tidak terintegrasi dengan pengaturan sumber daya (CPU, memori) yang disediakan systemd untuk service lain. Systemd timer adalah jawaban systemd untuk kebutuhan penjadwalan ini, dan karena hampir semua distro Linux modern (Ubuntu, Debian, Fedora, RHEL, Arch, openSUSE, dan lainnya) sudah memakai systemd sebagai init system, kemampuan ini tersedia luas tanpa perlu instalasi tambahan.

18.2.1 Kenapa Systemd Timer

Tabel berikut merangkum perbedaan paling relevan antara cron dan systemd timer untuk kebutuhan sehari-hari Sysadmin.

Aspekcronsystemd timer
LoggingManual, output harus di-redirect sendiriOtomatis tercatat ke journal, bisa dicari lewat journalctl
Jadwal terlewat saat matiJob yang seharusnya jalan saat server mati akan hilang begitu sajaBisa "menyusul" dijalankan sekali begitu server menyala lagi lewat opsi Persistent=
Kontrol sumber dayaTidak ada bawaanBisa dibatasi lewat opsi systemd yang sama dipakai service biasa (mis. MemoryMax=)
Ketergantungan antar tugasTidak ada mekanisme bawaanBisa diatur lewat After=/Requires= seperti service lain
Kurva belajarSatu baris teks, sangat ringkasButuh dua file unit terpisah, lebih verbose

Keunggulan systemd timer tidak membuat cron jadi usang. Untuk jadwal sederhana yang cukup satu baris dan tidak butuh fitur susulan atau kontrol sumber daya, cron tetap pilihan yang lebih cepat ditulis. Systemd timer lebih unggul untuk tugas yang penting tidak boleh terlewat (misalnya backup harian di laptop yang sering mati), atau yang perlu dipantau lebih ketat lewat log terstruktur.

18.2.2 Anatomi Unit Timer

Sebuah timer di systemd selalu berpasangan dengan sebuah service unit: timer mengatur kapan, service mengatur apa yang dijalankan. Secara konvensi, nama.timer otomatis memicu nama.service dengan nama dasar yang sama persis, kecuali ditentukan lain lewat opsi Unit=.

[Unit]
Description=Jadwal harian audit kondisi server

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true

[Install]
WantedBy=timers.target

OnCalendar= menentukan jadwal berbasis kalender, memakai sintaks yang didokumentasikan lengkap di man 7 systemd.time. Format *-*-* 02:00:00 di atas berarti "setiap hari, tanggal berapa pun, bulan apa pun, tahun berapa pun, pukul 02:00:00", setara dengan 0 2 * * * di cron. systemd.time juga menyediakan sejumlah kependekan yang lebih ringkas untuk pola umum: OnCalendar=daily, OnCalendar=weekly, OnCalendar=monthly, dan OnCalendar=hourly.

Persistent=true (default-nya false) adalah fitur "susulan" yang jadi salah satu alasan utama beralih ke systemd timer: kalau server dalam keadaan mati tepat saat timer seharusnya terpicu, systemd akan langsung menjalankannya sekali begitu server menyala kembali, alih-alih menunggu jadwal berikutnya. Satu catatan penting, opsi ini cuma berlaku untuk timer berbasis OnCalendar=; tidak berpengaruh apa-apa kalau dipasang di timer berbasis waktu relatif seperti OnBootSec= (sekian waktu setelah boot) dan OnUnitActiveSec= (sekian waktu setelah aktivasi terakhir unit itu sendiri), dua opsi jadwal relatif yang cocok untuk tugas yang cukup diulang secara berkala tanpa perlu jadwal jam pasti.

18.2.3 Membuat dan Mengaktifkan Timer

Langkah membuat timer baru selalu melibatkan dua file: service yang mendefinisikan tugasnya, dan timer yang mendefinisikan jadwalnya. Bagian anatomi service unit dibahas lebih dalam di 18.3; contoh berikut cukup memakai bentuk paling sederhana untuk fokus ke sisi penjadwalan lebih dulu. Buat dulu file service-nya.

sudo nano /etc/systemd/system/cek-disk.service
[Unit]
Description=Pengecekan cepat kondisi disk

[Service]
Type=oneshot
ExecStart=/usr/local/bin/cek-disk.sh

Lanjutkan dengan file timer pasangannya, nama dasarnya harus sama persis dengan file service di atas.

sudo nano /etc/systemd/system/cek-disk.timer
[Unit]
Description=Jadwal pengecekan disk tiap 30 menit

[Timer]
OnBootSec=5min
OnUnitActiveSec=30min

[Install]
WantedBy=timers.target

Simpan file unit baru ini di /etc/systemd/system/, direktori khusus konfigurasi lokal admin yang systemd prioritaskan dibanding unit bawaan distro di /usr/lib/systemd/system/. Setelah kedua file tersimpan, beri tahu systemd untuk membaca ulang konfigurasinya, lalu aktifkan timer-nya (bukan service-nya) memakai systemctl.

sudo systemctl daemon-reload
sudo systemctl enable --now cek-disk.timer

Jalankan daemon-reload setiap kali file unit baru dibuat atau diubah, supaya systemd tahu ada definisi baru sebelum dipakai. enable --now melakukan dua hal sekaligus: enable mendaftarkan timer supaya aktif otomatis tiap kali server boot (lewat WantedBy=timers.target di bagian [Install]), dan --now langsung menjalankannya saat itu juga tanpa perlu menunggu boot berikutnya.

Verifikasi bahwa timer sudah terdaftar dan tahu kapan giliran berikutnya jalan lewat list-timers.

systemctl list-timers cek-disk.timer

Output-nya mencantumkan kolom NEXT (kapan giliran berikutnya) dan LAST (kapan terakhir kali terpicu), jauh lebih informatif dibanding crontab -l yang cuma menampilkan definisi jadwalnya tanpa tahu kapan realisasinya.

18.3 Menjalankan Script sebagai Service

Sub-bab 18.2 sempat menyinggung service unit sekilas sebagai pasangan timer. Sub-bab ini membahas anatomi service unit itu lebih dalam, karena kegunaannya sebenarnya jauh lebih luas dari sekadar jadi target sebuah timer, service unit juga jadi cara standar menjalankan aplikasi atau daemon kustom di server, lengkap dengan kemampuan restart otomatis kalau crash.

18.3.1 Anatomi Unit Service

Sebuah file unit .service terdiri dari tiga bagian utama: [Unit] untuk metadata dan relasi dengan unit lain, [Service] untuk perilaku eksekusinya, dan [Install] untuk aturan kapan unit ini diaktifkan.

[Unit]
Description=Aplikasi web internal
After=network.target

[Service]
Type=simple
User=deploy
WorkingDirectory=/opt/aplikasi
ExecStart=/opt/aplikasi/jalankan.sh
Restart=on-failure

[Install]
WantedBy=multi-user.target

Direktif Type= menentukan bagaimana systemd memperlakukan proses yang dijalankan. Type=simple (default kalau Type= tidak ditulis) mengasumsikan proses di ExecStart= adalah proses utama yang terus berjalan di foreground selama service itu dianggap aktif, cocok untuk daemon jangka panjang seperti aplikasi web di atas. Type=oneshot, seperti dipakai untuk cek-disk.service di 18.2.3, sebaliknya mengasumsikan proses itu akan selesai dan keluar dengan sendirinya, cocok untuk script sekali jalan yang dipicu timer atau dijalankan manual, bukan daemon yang harus terus hidup.

User= menjalankan proses sebagai user tertentu alih-alih root, konsisten dengan prinsip hak akses minimal yang sudah disinggung di Bab 17.3.3. Restart=on-failure memerintahkan systemd menjalankan ulang service secara otomatis kalau prosesnya berhenti dengan exit status bukan nol, kemampuan yang sama sekali tidak dimiliki cron secara bawaan. WantedBy=multi-user.target di bagian [Install] berarti service ini ikut aktif otomatis setiap kali server masuk ke target multi-user standar, yaitu kondisi normal server menyala dan siap dipakai.

18.3.2 Mengelola Service dengan systemctl

systemctl adalah satu perintah tunggal untuk mengelola seluruh siklus hidup sebuah unit, baik service maupun timer.

sudo systemctl start aplikasi-web.service
sudo systemctl stop aplikasi-web.service
sudo systemctl restart aplikasi-web.service
systemctl status aplikasi-web.service

start, stop, dan restart cukup jelas dari namanya; ketiganya cuma memengaruhi kondisi saat ini, tidak mengubah apakah service itu otomatis aktif lagi setelah reboot. status mencetak ringkasan kondisi terkini, termasuk apakah sedang active (running) atau failed, PID proses utamanya, dan beberapa baris log terakhir. Untuk mengatur perilaku saat boot, dipakai perintah terpisah.

sudo systemctl enable aplikasi-web.service
sudo systemctl disable aplikasi-web.service

enable membuat symlink di direktori target yang sesuai (mengacu ke WantedBy= di file unit-nya) supaya service otomatis dimulai tiap kali server boot; disable mencabut symlink itu tanpa menghentikan service yang sedang berjalan saat itu juga. Perbedaan ini sering bikin bingung pemula: enable tanpa start membuat service baru aktif di boot berikutnya, tidak langsung saat itu, itulah kenapa enable --now yang dipakai di 18.2.3 lebih praktis untuk kebanyakan kasus.

Log setiap service yang dikelola systemd otomatis tertampung ke journal tanpa perlu konfigurasi tambahan apa pun, kelebihan yang sudah disinggung di 18.2.1.

journalctl -u aplikasi-web.service
journalctl -u aplikasi-web.service -f
journalctl -u aplikasi-web.service --since today

Opsi -f (follow) menampilkan log baru secara real-time, mirip tail -f dari Bab 2.3, sedangkan --since today menyaring log cuma dari hari itu saja, jauh lebih praktis dibanding menelusuri file log manual yang harus di-rotate sendiri seperti kebiasaan lama di cron.

18.3.3 Service User vs Service System

Service unit yang dibahas sejauh ini disebut system service, disimpan di /etc/systemd/system/, dikelola dengan hak akses root lewat sudo, dan berjalan lepas dari sesi login siapa pun. Untuk kebutuhan otomatisasi di level user biasa, misalnya reminder desktop yang sempat disinggung sekilas di Bab 15.1, systemd juga menyediakan user service yang tidak butuh hak akses root sama sekali.

mkdir -p ~/.config/systemd/user
nano ~/.config/systemd/user/reminder.service
[Unit]
Description=Reminder minum air tiap jam

[Service]
Type=oneshot
ExecStart=/usr/bin/notify-send "Waktunya minum air"

Perbedaan utamanya cuma di lokasi file dan perintah yang dipakai, ditambahkan flag --user di setiap pemanggilan systemctl.

systemctl --user daemon-reload
systemctl --user enable --now reminder.timer

User service secara default berhenti begitu user itu logout, karena terikat pada sesi session bus user yang bersangkutan. Untuk kasus di server yang butuh user service tetap berjalan meski user itu tidak sedang login secara aktif (misalnya lewat SSH yang terputus), root perlu mengaktifkan lingering untuk user tersebut.

sudo loginctl enable-linger deploy

enable-linger membuat systemd tetap menjalankan service manager milik user deploy di background meski tidak ada sesi login aktif sama sekali, membuat user service-nya berperilaku setara system service dari sisi ketahanan, tanpa perlu hak akses root untuk mengelola isi service-nya sehari-hari.

18.4 Studi Kasus: Script Maintenance Server Terjadwal

Studi kasus penutup ini menjadwalkan ulang audit-server.sh dari Bab 17.4 lewat kedua metode yang dibahas bab ini, cron dan systemd timer, supaya perbedaan keduanya terlihat jelas lewat kasus yang sama persis, bukan cuma lewat penjelasan teori. Pola menjadwalkan script audit seperti ini juga jadi fondasi untuk topik alerting otomatis di Bab 20, di mana exit status 1 dari script itu bisa dijadikan pemicu notifikasi begitu ada filesystem yang melewati ambang batas.

18.4.1 Rancangan Penjadwalan

Script audit-server.sh diasumsikan sudah dipindahkan ke /usr/local/bin/audit-server.sh dan diberi izin eksekusi, lokasi standar untuk script kustom yang dipakai luas di seluruh sistem, konsisten dengan path absolut yang dibahas di 18.1.3. Rancangannya menjalankan audit ini setiap hari pukul 02:00, waktu yang lazim dipilih Sysadmin karena trafik server biasanya paling sepi. Versi cron tetap menyimpan hasilnya ke file log bertanggal seperti contoh Bab 17.4.3, sedangkan versi systemd timer sengaja dibuat tanpa opsi -o sama sekali, karena output-nya sudah otomatis tertampung rapi ke journal lengkap dengan cap waktu tiap kali dijalankan, sesuai kelebihan yang dibahas di 18.3.2.

18.4.2 Implementasi Cron dan Systemd Timer

Versi cron dipasang lewat crontab -e.

MAILTO=""
0 2 * * * /usr/local/bin/audit-server.sh -t 80 -o /var/log/audit-server/audit-$(date +\%Y\%m\%d).log

Perhatikan tanda garis miring terbalik sebelum tiap % di bagian date +\%Y\%m\%d. Ini bukan salah ketik: menurut man 5 crontab, tanda persen (%) yang tidak di-escape di dalam field perintah crontab otomatis diubah jadi karakter baris baru, dan semua teks setelah tanda % pertama malah dikirim sebagai stdin ke perintah itu, bukan diperlakukan sebagai bagian dari perintahnya. Tanpa \ di depan tiap %, perintah date di atas akan rusak total dan bukan cuma menghasilkan nama file yang salah. Ini salah satu jebakan cron yang paling sering luput disadari, karena perintah yang sama persis berjalan normal saat dites manual di terminal, dan baru terlihat rusak setelah dipasang ke crontab.

Versi systemd timer dipasang lewat dua file unit baru.

sudo nano /etc/systemd/system/audit-server.service
[Unit]
Description=Audit kondisi server harian

[Service]
Type=oneshot
ExecStart=/usr/local/bin/audit-server.sh -t 80
sudo nano /etc/systemd/system/audit-server.timer
[Unit]
Description=Jadwal harian audit kondisi server

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true

[Install]
WantedBy=timers.target

Persistent=true di sini dipasang secara sengaja, berbeda dari contoh cek-disk.timer di 18.2.3 yang jadwalnya berbasis interval pendek (OnUnitActiveSec=30min). Audit harian jauh lebih penting untuk "menyusul" dijalankan kalau server kebetulan sedang di-maintenance atau mati tepat pukul 02:00, dibanding pengecekan disk tiap 30 menit yang toh akan terpicu lagi tidak lama kemudian meski satu kali kesempatan terlewat.

sudo systemctl daemon-reload
sudo systemctl enable --now audit-server.timer

18.4.3 Verifikasi dan Troubleshooting

Untuk versi cron, pastikan dulu baris barunya benar-benar tersimpan, lalu tunggu jadwalnya atau uji manual dengan menjalankan perintah persis seperti yang tertulis di crontab (tanpa \ di depan %, karena di terminal biasa tanda persen tidak butuh escape).

crontab -l
/usr/local/bin/audit-server.sh -t 80 -o /var/log/audit-server/audit-$(date +%Y%m%d).log
cat /var/log/audit-server/audit-*.log

Kalau job tidak juga muncul hasilnya sesuai jadwal, urutan pengecekan yang wajar: pastikan service cron sendiri hidup (systemctl status cron atau systemctl status crond), cek log aktivitas cron lewat journalctl -u cron untuk memastikan job itu benar-benar terpicu, lalu baru curigai isi script atau masalah PATH dari 18.1.3 kalau job terpicu tapi hasilnya kosong atau error.

Untuk versi systemd timer, list-timers memastikan jadwalnya terdaftar dengan benar, lalu journalctl memastikan hasil audit terakhir tercatat.

systemctl list-timers audit-server.timer
journalctl -u audit-server.service --since today

Kalau timer terdaftar tapi service-nya gagal jalan, systemctl status audit-server.service mencetak exit code terakhir beserta beberapa baris log paling relevan. Kesalahan sintaks kecil di file unit sendiri, misalnya lupa tanda = atau salah nama section, bisa dicek lebih dulu tanpa perlu menjalankannya sama sekali lewat systemd-analyze verify.

systemd-analyze verify /etc/systemd/system/audit-server.service

Dua pendekatan di studi kasus ini, cron yang ringkas dan systemd timer yang lebih verbose tapi lebih tangguh, sama-sama valid dipakai di server produksi, dan pilihan di antara keduanya lebih soal kebutuhan spesifik dibanding mana yang "lebih benar". Bab 19 melanjutkan dari sini dengan membahas journalctl dan pengelolaan log lebih dalam, modal penting untuk memantau hasil job-job terjadwal seperti ini dalam skala yang lebih besar.