03 / PANDUAN
Menulis ekspresi cron yang tidak memicu kejutan
Lima field dan rentangnya, nama versus angka, jebakan OR antara tanggal dan hari, Minggu sebagai 0 atau 7, celah dan tumpang tindih daylight saving, serta validasi dengan pratinjau eksekusi berikutnya sebelum deploy.
Lima field, dibaca dari kiri ke kanan
Ekspresi cron klasik terdiri dari lima field yang dipisah spasi: menit (0–59), jam (0–23), tanggal (1–31), bulan (1–12), dan hari (0–7). Setiap field menerima satu nilai, daftar berkoma, rentang ber-tanda hubung, langkah setelah garis miring, atau tanda bintang untuk semua nilai.
Kebanyakan bug cron bukan sintaks eksotis melainkan field biasa yang dibaca ceroboh: langkah yang ter-reset di batas rentang, atau field jam yang ditulis untuk jam dua belas dalam sistem yang menghitung sampai dua puluh tiga.
- DaftarDaftar memilih nilai diskrit: 0,30 di field menit menyala pada menit nol dan menit tiga puluh setiap jam.
- Rentang dan langkahRentang memilih satu span: 9-17 di field jam mencakup jam kerja, dan langkah menipiskannya—9-17/2 menyala setiap dua jam di dalam span itu.
- Bintang cocok semuaTanda bintang bukanlah “abaikan field ini”; ia aktif mencocokkan setiap nilai, yang menjadi penting begitu dua field hari berinteraksi.
Nama adalah angka dengan dokumentasi lebih baik
Field bulan dan hari menerima nama Inggris tiga huruf—JAN sampai DEC dan SUN sampai SAT—sebagai alias angkanya. 0 9 * JAN MON dan 0 9 * 1 1 adalah jadwal yang sama, tetapi versi bernama menjelaskan dirinya kepada pembaca berikutnya dan tahan terhadap edit off-by-one.
- Tanpa huruf besar-kecilNama diparse tanpa membedakan huruf besar-kecil—mon, Mon, dan MON semuanya bisa—tetapi huruf besar adalah konvensi yang terbaca disengaja.
- Nama dalam rentangNama juga bekerja di dalam rentang dan daftar: MON-FRI adalah span hari kerja standar, dan JAN,APR,JUL,OCT memilih bulan-bulan triwulanan.
- Baca penjelasannyaPembuat dan penjelas Cron menormalkan ekspresi dan menjelaskan setiap field secara terpisah—“month: every value”, “weekday: 1, 2, 3, 4, 5”—sehingga Anda bisa memastikan parser membaca nama persis seperti maksud Anda.
Dua field hari digabung dengan OR
Inilah kejutan cron yang paling mahal: ketika tanggal dan hari sama-sama dibatasi—tidak ada yang berupa tanda bintang—jadwal menyala ketika salah satu cocok. 0 9 13 * FRI bukan berarti “Jumat tanggal 13”; artinya tanggal 13 setiap bulan dan setiap hari Jumat.
Output penjelas eksplisit soal ini: ia melaporkan semantiknya sebagai dom-dow-or di samping eksekusi yang dihitung, sehingga ekspresi yang akan menyala jauh lebih sering dari maksudnya menunjukkan belangnya sebelum masuk crontab.
- Satu wildcard itu sederhanaBila salah satu field hari adalah tanda bintang, yang lain berkuasa sendirian—perilaku intuitif yang dikira kebanyakan orang berlaku di mana-mana.
- Dua-duanya dibatasi berarti ORKeduanya dibatasi berarti OR: semantik Vixie cron klasik, yang diikuti sebagian besar penjadwal Unix, menjalankan tugas ketika tanggal cocok atau hari cocok.
- AND butuh akal-akalanUntuk benar-benar mengenai Jumat tanggal 13, biarkan cron memilih tanggal 13 dan minta perintahnya sendiri memeriksa hari—atau pakai penjadwal dengan semantik AND, yang bukan cron klasik.
Minggu adalah 0, dan biasanya juga 7
Field hari menomori Minggu sebagai 0, Senin sebagai 1, dan seterusnya sampai Sabtu sebagai 6. Sebagian besar implementasi juga menerima 7 sebagai Minggu kedua bagi yang menghitung dari Senin—parser Toolars menormalkan 7 menjadi 0 secara internal—tetapi sebagian sistem hanya menerima salah satu, dan penomoran gaya ISO yang memulai Senin di 1 ada di tempat lain.
- 0 dan 70 dan 7 sama-sama Minggu di tempat 7 diterima; menulis 0 adalah pilihan yang portabel lintas penjadwal.
- Off-by-one diam-diamHari bernilai 7 pada sistem yang menolaknya gagal dengan keras saat deploy, tetapi hari yang salah dibaca sebagai “hari ketujuh dihitung dari Senin” gagal diam-diam di hari yang salah.
- Konfirmasi per platformKetika ekspresi berpindah antar implementasi—crontab sistem, platform kontainer, penjadwal CI—konfirmasi ulang penomoran harinya alih-alih mengasumsikannya selamat dalam perjalanan.
Daylight saving membengkokkan jadwal
Cron menyala pada waktu jam dinding di zona waktu penjadwal, dan dua kali setahun jam dinding berulah. Pada celah maju di musim semi, waktu lokal seperti 02:30 sama sekali tidak ada; pada mundur di musim gugur, waktu itu ada dua kali. Jadwal yang dipaku pada menit itu akan melewatkan satu eksekusi di bulan Maret dan mungkin menyala dua kali di bulan November.
- Jam yang hilangCelah musim semi: tugas 02:30 pada malam transisi tidak punya waktu dinding yang cocok, jadi tidak ada yang menyala—tanpa error, tanpa coba ulang, hanya eksekusi yang hilang.
- Jam yang menggandaTumpang tindih musim gugur: waktu dinding yang sama terjadi dua kali, dan implementasi berbeda soal tugas menyala sekali atau dua kali; asumsikan dua kali kecuali Anda sudah memverifikasi sebaliknya.
- UTC tanpa DSTJalan keluar yang bersih adalah UTC: tidak ada transisi daylight saving, jadi 30 2 * * * berarti momen yang sama setiap hari sepanjang tahun. Penjelas menawarkan UTC, zona lokal perangkat, dan zona bernama seperti America/New_York dan Europe/London.
Validasi dengan eksekusi berikutnya, bukan harapan
Perbedaan antara ekspresi yang benar dan yang kelihatan masuk akal adalah daftar waktu penyalaan yang konkret. Pembuat dan penjelas Cron menghitung sepuluh eksekusi berikutnya dari sekarang dalam zona waktu pilihan Anda, mencari hingga 366 hari ke depan, dan mengevaluasi di worker latar sehingga ekspresi berat tidak bisa menghentikan tab.
- Baca eksekusinyaBaca beberapa eksekusi pertama terhadap maksud: “hari kerja pukul 09:00” harus menampilkan Senin sampai Jumat pukul sembilan, dan satu Sabtu di daftar adalah jebakan OR yang mengumumkan dirinya.
- Lintasi satu transisiLintasi batas daylight saving dengan sengaja: pilih tanggal di Maret atau November pada zona bernama dan pastikan jadwal tetap sesuai harapan saat jam bergeser.
- Error eksplisitKegagalan bersifat eksplisit: field tidak valid, jumlah field salah, atau jadwal yang tidak bisa menghasilkan sepuluh eksekusi dalam jendela pencarian masing-masing mendapat error bernama, bukan daftar kosong yang sunyi.
Jadwal dan pola berbagi disiplin yang sama.
Keduanya string kecil dengan radius kerusakan besar—pelajari loop tulis-uji-refaktor untuk ekspresi reguler, dijalankan di worker lokal dengan batas waktu.