Backup tiap malam, pembersihan log tiap pekan, sinkronisasi data tiap lima menit — pekerjaan berulang seperti ini tidak seharusnya dikerjakan manusia. Masalahnya ada dua lapis: bagaimana Python menjalankan pekerjaan secara berkala, dan bagaimana sistem operasi membangunkan program kita pada waktunya. Chapter ini membahas pola loop sederhana, jadwal yang stabil tanpa drift, library penjadwal, hingga cron dan systemd timer.
Loop Sederhana dengan time.sleep #
Cara paling naif: loop while yang bekerja lalu tidur selama interval. Berkas loop_sederhana.py:
import time
def kirim_laporan(nomor):
print(f"laporan #{nomor} terkirim")
for nomor in range(1, 4):
kirim_laporan(nomor)
time.sleep(0.2)
print("siklus selesai")Output yang Dihasilkan (tiga baris pertama berjarak 0,2 detik pada eksekusi nyata):
laporan #1 terkirim
laporan #2 terkirim
laporan #3 terkirim
siklus selesaiPola ini sah untuk kebutuhan sederhana, tetapi punya dua kelemahan. Pertama, program harus terus berjalan — begitu proses mati atau laptop dimatikan, jadwal berhenti. Kedua, waktu eksekusi pekerjaan ikut menambah periode, sehingga jadwal bergeser pelan-pelan; gejala ini bernama drift.
Drift dan Penjadwalan Stabil #
Drift terjadi karena sleep(60) menunggu 60 detik setelah pekerjaan selesai, bukan 60 detik sejak jadwal sebelumnya. Solusinya: hitung waktu target berikutnya dari satu titik nol, lalu tidur selama sisa waktu menuju target. Berkas jadwal_tanpa_drift.py:
import time
mulai = time.monotonic()
interval = 60.0
for nomor in (1, 2):
target = mulai + nomor * interval
print(f"run {nomor} dijadwalkan pada detik ke-{target - mulai:.0f}")Output yang Dihasilkan:
run 1 dijadwalkan pada detik ke-60
run 2 dijadwalkan pada detik ke-120Nilai kembalian time.monotonic() hanya cocok untuk mengukur selisih waktu — nilainya tidak pernah mundur meski jam sistem diubah — sehingga perhitungan target - sekarang selalu benar. Dengan pola sleep(max(0, target - time.monotonic())), pekerjaan yang memakan 10 detik hanya tidur 50 detik lagi, dan run ke-2 tetap jatuh tepat di detik ke-120.
Konsekuensi lain yang jarang disadari: bila laptop tertidur atau program mati, run yang terlewat tidak dikejar. Baik loop tidur maupun cron sama-sama berkomitmen hanya pada jadwal berikutnya, bukan jadwal yang hilang.
Library schedule untuk Job di Dalam Program #
Ketika jadwal tinggal di dalam satu program Python, library schedule (paket pihak ketiga) memungkinkan penulisan jadwal yang terbaca seperti kalender:
import schedule
import time
def backup_harian():
print("menjalankan backup")
schedule.every().day.at("06:30").do(backup_harian)
schedule.every(10).minutes.do(backup_harian)
while True:
schedule.run_pending()
time.sleep(1)Blok di atas adalah ilustrasi API schedule — pada lingkungan penulisan chapter ini paket tersebut tidak terpasang, sehingga contoh tidak disertai output eksekusi. Pola kerjanya: do() mendaftarkan fungsi ke jadwal, lalu loop run_pending() memeriksa setiap detik mana yang jatuh temponya.
cron dan systemd timer di Sistem Operasi #
Untuk pekerjaan yang harus hidup terlepas dari program kita, penjadwal milik sistem operasi lebih tepat. Di Linux dan macOS, cron membaca tabel jadwal bernama crontab dengan lima kolom waktu:
| Kolom | Nilai | Contoh |
|---|---|---|
| menit | 0-59 | 30 |
| jam | 0-23 | 6 |
| tanggal bulan | 1-31 | * |
| bulan | 1-12 | * |
| hari minggu | 0-6 (0 = Minggu) | * |
Entri crontab berikut menjalankan skrip backup setiap hari pukul 06:30:
30 6 * * * /usr/bin/python3 /home/budi/backup.py >> /home/budi/backup.log 2>&1Bintang * berarti “apa pun nilainya”, dan >> ... 2>&1 menampung semua output ke satu berkas log. Variasi yang sering dipakai:
*/15 * * * * setiap 15 menit
0 3 * * 1 setiap Senin pukul 03:00
0 0 1 * * tanggal 1 setiap bulanKelola tabel tersebut dengan crontab -e (mengedit) dan crontab -l (menampilkan). Di Linux modern, systemd timer adalah alternatif dengan log terpadu (journalctl) dan dependensi antar unit; keduanya dipilih berdasarkan selera tim. Pengguna Windows memakai Task Scheduler yang menyediakan antarmuka grafis dengan kemampuan setara.
Job yang Idempoten dan Terawasi #
Penjadwal sistem tidak menjamin job hanya berjalan sekali — tumpang tindih terjadi saat durasi melebihi interval, atau saat dua instance sengaja dijalankan. Karena itu rancang job secara idempoten: menjalankannya dua kali menghasilkan efek yang sama dengan sekali. Contoh nyata: berkas backup bernamai backup-2025-06-15.tar.gz akan menimpa hasil sebelumnya alih-alih menggandakan berkas, dan tabel sinkronisasi memakai primary key sehingga data terduplikasi tertolak.
Kedua, job terjadwal berjalan tanpa saksi, sehingga logging adalah satu-satunya mata kita. Setiap job selayaknya mencatat kapan mulai, kapan selesai, dan ringkasan hasilnya — pola logging yang baik dibahas pada Chapter Module logging di section Debugging dan Logging. Terakhir, satukan job menjadi perintah tunggal yang jelas, misalnya python3 pekerjaan.py --job backup, sehingga jadwal sistem hanya memanggil satu entry point yang bisa pula diuji manual kapan pun.
Setelah pekerjaan terjadwal, kita berpindah ke wilayah otomasi paling dekat dengan file system: rename massal, pembersihan berkas tua, dan laporan ukuran.