Cron Job dan Zona Waktu: Mengapa Jadwal Anda Berjalan di Jam yang Salah
Oleh Redaksi Safe Local Tools
Cron job Anda tidak “rusak secara acak”—ia dipicu dalam UTC sementara Anda berpikir dengan waktu lokal. Penjadwalan terlihat sepele sampai offset musim panas menggeser satu jam, Kubernetes memakai dialek cron berbeda dari Linux, dan satu * di field yang salah menjalankan tugas pembersihan setiap menit alih-alih setiap bulan.
Panduan ini menjelaskan field cron, jebakan zona waktu, perbedaan platform, serta cara memvalidasi jadwal dengan analisis Safe Local Tools secara lokal di browser sebelum mencapai produksi.
Memahami cron berarti mengakui bahwa konfigurasi adalah eksekusi kode jarak jauh pada timer—tim DevOps yang mengabaikan dialek atau zona sering membayarnya dengan insiden larut malam yang sebenarnya dapat dicegah dengan checklist yang disiplin.

Cron dalam satu paragraf (dan mengapa dialek berbeda)
Cron klasik punya lima field: menit, jam, tanggal dalam bulan, bulan, hari dalam minggu. Beberapa sistem menambahkan detik (enam field) atau tahun. Tiap field mendukung * untuk semua nilai, koma untuk daftar, rentang dengan -, dan langkah dengan /.
Tidak ada cron universal. crontab Linux, pintasan seperti @hourly, Quartz di Jawa, AWS EventBridge, serta CronJob Kubernetes masing-masing memperluas atau membatasi sintaks secara berbeda. Menyalin-tempel antar sistem adalah sumber pemadaman yang umum.
UTC dibanding lokal: pilih satu dan dokumentasikan
Server sering berjalan UTC; manusia merencanakan dalam America/New_York atau Asia/Jakarta. Celah itu menghasilkan laporan yang ‘hilang’ satu jam saat musim panas maju, duplikasi eksekusi saat jam mundur jika Anda menyimpan instan lokal secara naif, serta alarm yang direncanakan untuk jam kerja tetapi bergeser dua kali setahun.
Praktik baik: simpan jadwal dalam UTC pada konfigurasi; tampilkan perkiraan eksekusi berikutnya dalam zona bisnis menggunakan basis data zona IANA pada lapisan UI.
Interaksi hari-minggu versus tanggal-minggu
Beberapa mesin memperlakukan kombinasi day-of-week dan day-of-month sebagai OR; lain sebagai AND. Niatan seperti ‘hari kerja jam 9 pagi’ memerlukan kedua dimensi diisi dengan benar.
Misconfigured * pada tanggal bulan sementara Anda menyebut hari tertentu masih bisa menyala di akhir pekan bergantung implementasi—selalu cetak sepuluh eksekusi berikutnya untuk konfirmasi.
Senjata kaki sendiri */5
*/5 pada field menit berarti setiap lima menit. Pada field jam berarti setiap lima jam. Pemula menempel */5 * * * * mengharapkan ‘setiap lima jam’ dan mendapat badai job.
Perbaikan: tuliskan deskripsi manusiawi di samping ekspresi di Git dan tinjau dalam PR.
Detail Kubernetes CronJob
Kubernetes memakai cron lima-field standar (tanpa detik). Kebijakan konkurensi Forbid, Allow, atau Replace mengubah perilaku ketika job bertumpuk.
startingDeadlineSeconds dapat melewatkan eksekusi yang tertinggal setelah outage—mengejutkan jika Anda mengharapkan pengumpulan backlog.
suspend mengaktifkan/menonaktifkan tanpa menghapus CRD.
Uji sekali pakai dengan kubectl create job --from=cronjob/... daripada menunggu jarum jam.
Quartz dan penjadwal enterprise
Java Quartz menambahkan ? dan nama bulan/hari; Spring @Scheduled bisa berbeda lagi. Jika satu layanan memakai Quartz dan lainnya cron Linux, pertahankan cheat sheet dialek yang ditinjau bersama.
Ekspresi rate AWS EventBridge
rate(5 minutes) dan cron(0 12 * * ? *) hidup berdampingan tetapi bukan bahasa yang sama. Mencampur keduanya dalam runbook membingungkan engineer bertugas.
Musim panas: maju dan mundur
Saat jam loncat maju, waktu lokal yang tidak ada harus ditolak atau digeser—tetapkan kebijakan. Saat jam mundur, satu jam berulang; job bisa berlari dua kali kecuali Anda mendeduplikasi dengan id eksekusi.
Gunakan UTC secara internal; lokalkan hanya untuk tampilan.
Monitoring eksekusi yang terlewat
Instrumentasikan last_success_timestamp, durasi terakhir, dan alarm ketika tidak ada sukses dalam kelipatan interval yang masuk akal.
Keheningan cron lebih berbahaya daripada kebisingan cron—job yang gagal tanpa alarm mengikis kepercayaan pada pipeline data.
Uji ekspresi sebelum deploy
Parse dalam dialek yang sama dengan produksi.
Cetak sepuluh eksekusi berikutnya dalam UTC dan zona bisnis Anda.
Bandingkan dengan referensi publik untuk dialek yang sama.
Dry-run perintah tanpa efek samping.
Parser cron Safe Local Tools berjalan di sisi klien—berguna ketika Anda tidak bisa menempel nama job internal ke situs publik.
Cron sebagai eksekusi kode jarak jauh
Cron adalah RCE berjadwal. Lindungi siapa yang boleh mengedit CronJob atau crontab, rahasia yang dipasang ke pod kerja batch, serta egress jaringan dari worker.
Idempotensi untuk efek samping
Job yang mengenakan biaya atau mengirim email harus idempoten. Gunakan id deterministik dari waktu eksekusi terjadwal plus penyewa agar duplikasi pada jam DST mundur tidak menggandakan tagihan.
Cron versus worker antrian
Tugas periodik ber-volume tinggi sering lebih cocok pada antrian dengan backoff daripada satu tick cron yang harus selesai sebelum tick berikutnya. Pertimbangkan cron untuk mengantrikan pekerjaan, bukan menyelesaikan seluruhnya secara inline ketika runtime bervariasi lebar.
Regresi DST dalam tes otomatis
Unit test yang memanggil jam sistem gemetar di perbatasan. Injeksikan jam palsu atau perpustakaan pembekuan waktu pada instan seperti pergantian musim panas Chicago atau Sydney untuk menegaskan perilaku yang Anda harapkan dari zona pelanggan nyata.
Error cron adalah error konfigurasi, bukan misteri. Selaraskan dialek, jangkar zona dalam UTC, dan selalu pratinjau eksekusi berikutnya sebelum merge.
Saat Anda membutuhkan waktu eksekusi berikutnya tanpa mengirim jadwal internal ke pihak ketiga, Coba Parser Ekspresi Cron →