Cheat Sheet Crontab: 50+ Ekspresi Cron, Sintaks, dan Panduan Scheduler Modern
Ekspresi cron terdiri dari lima kolom (menit, jam, hari-dalam-bulan, bulan, hari-dalam-minggu) diikuti sebuah perintah. Tata bahasa itulah yang menjalankan penjadwalan Unix sejak 1979 dan kini dipakai Kubernetes CronJob, GitHub Actions, AWS EventBridge, dan trigger cron Vercel. Pelajari sekali, pakai di banyak tempat.
Halaman ini ditujukan untuk developer yang butuh ekspresi sekarang juga: task Linux, Kubernetes CronJob, trigger GitHub Actions, atau debug job lima menit yang malah hanya berjalan tiap jam. Tabel Referensi Cepat di bawah berisi ekspresi siap salin; bagian Sintaks Dibedah menjelaskan aturan tiap kolom; Generator Crontab — alternatif crontab guru yang mengutamakan privasi dan berjalan di browser Anda — memvalidasi ekspresi secara langsung.
Tabel Referensi Cepat Ekspresi Cron
Tiga puluh ekspresi yang menutup sekitar 90% kebutuhan penjadwalan nyata. Setiap baris adalah cron POSIX lima-kolom yang valid: tempel ke crontab -e, ke schedule: Kubernetes, atau ke cron: GitHub Actions.
| Jadwal | Ekspresi Cron | Penjelasan |
|---|---|---|
| Setiap menit | * * * * * | tiap menit, sepanjang hari, setiap hari |
| Setiap 5 menit | */5 * * * * | menit 0, 5, 10, …, 55 |
| Setiap 15 menit | */15 * * * * | menit 0, 15, 30, 45 |
| Setiap 30 menit | */30 * * * * | menit 0 dan 30 |
| Setiap jam | 0 * * * * | tepat di awal tiap jam |
| Setiap 2 jam | 0 */2 * * * | jam 0, 2, 4, …, 22 |
| Setiap 6 jam | 0 */6 * * * | jam 0, 6, 12, 18 |
| Dua kali sehari (09.00 + 21.00) | 0 9,21 * * * | menit 0 di jam 9 dan 21 |
| Setiap hari kerja pukul 09.00 | 0 9 * * 1-5 | Sen-Jum 09.00 |
| Setiap akhir pekan pukul 09.00 | 0 9 * * 0,6 | Sab dan Min 09.00 |
| Harian tengah malam | 0 0 * * * | tiap hari 00.00 |
| Harian pukul 02.30 | 30 2 * * * | jendela batch saat trafik rendah |
| Setiap Senin pukul 09.00 | 0 9 * * 1 | Senin 09.00 |
| Setiap Jumat pukul 17.00 | 0 17 * * 5 | Jumat 17.00 |
| Setiap Minggu tengah malam | 0 0 * * 0 | setara @weekly |
| Tanggal 1 tiap bulan tengah malam | 0 0 1 * * | tanggal 1 pukul 00.00 — setara @monthly |
| Tanggal 15 tiap bulan tengah hari | 0 12 15 * * | jendela payroll pertengahan bulan |
| Cek hari terakhir (wrapper) | 0 0 28-31 * * + skrip | perlu cek tanggal |
| Kuartalan (1 Jan/Apr/Jul/Okt) | 0 0 1 JAN,APR,JUL,OCT * | hari pertama tiap kuartal |
| Tahunan (1 Jan) | 0 0 1 1 * atau @yearly | tahun baru tengah malam |
| Setiap 5 menit di hari kerja 9-17 | */5 9-17 * * 1-5 | polling di jam kerja |
| Setiap 30 menit di akhir pekan | */30 * * * 0,6 | monitoring Sab/Min |
| Dua kali tiap jam, menit 15 dan 45 | 15,45 * * * * | menghindari “tabrakan” menit :00 |
| Senin pertama (wrapper) | 0 9 1-7 * 1 + cek AND | butuh wrapper (lihat bawah) |
| Macro | @hourly @daily @weekly @monthly @yearly | non-standar tetapi luas didukung |
| Hanya saat reboot | @reboot | non-standar, hanya vixie cron |
Tempelkan ekspresi mana pun ke Generator Crontab untuk melihat pratinjau lima eksekusi berikutnya. Itu uji cepat termurah sebelum deploy.
Sintaks Cron Dibedah: 5 Kolom
Ekspresi cron terdiri dari lima kolom dipisah spasi plus sebuah perintah. Setiap kolom mengontrol satu irisan jadwal. Inilah inti sintaks ekspresi cron di semua scheduler dalam panduan ini.
┌──────────── menit (0 - 59)
│ ┌────────── jam (0 - 23)
│ │ ┌──────── hari-bulan (1 - 31)
│ │ │ ┌────── bulan (1 - 12 atau JAN-DEC)
│ │ │ │ ┌──── hari-minggu (0 - 6 atau SUN-SAT; 0 dan 7 sama-sama Minggu)
│ │ │ │ │
* * * * * perintah-yang-dijalankan
Mnemonik: “Mari Jadwalkan Hari Bulan Wajar”, untuk Menit, Jam, Hari-bulan, Bulan, Hari-minggu. Kiri ke kanan, dari satuan terkecil ke terbesar.
Nilai yang diizinkan per kolom
| Kolom | Rentang | Alias | Catatan |
|---|---|---|---|
| Menit | 0-59 | tidak ada | 0 berarti “tepat di awal jam” |
| Jam | 0-23 | tidak ada | jam 24; 0 tengah malam, 12 tengah hari |
| Hari-bulan | 1-31 | tidak ada | tanggal yang tidak valid di suatu bulan diam-diam tidak pernah dipicu (31 Feb) |
| Bulan | 1-12 | JAN, FEB, MAR, …, DEC | tidak peka huruf besar/kecil |
| Hari-minggu | 0-7 | SUN, MON, TUE, …, SAT | 0 dan 7 keduanya berarti Minggu |
Operator secara rinci
Lima operator mencakup semua ekspresi cron standar:
| Operator | Arti | Contoh | Diperluas menjadi |
|---|---|---|---|
* | nilai apa pun | * * * * * | tiap menit |
, | daftar | 0 9,12,17 * * * | 09.00, 12.00, 17.00 |
- | rentang inklusif | 0 9-17 * * * | tiap jam 09.00 hingga 17.00 |
/ | langkah (step) | */15 * * * * | menit 0, 15, 30, 45 |
| campuran | gabungan | 0 9-12,14-17 * * * | pagi + sore, lewati makan siang |
Operator step pantas diperhatikan. */N berjangkar pada nilai terkecil kolom, bukan waktu saat ini. */15 berarti “menit 0, 15, 30, 45 di tiap jam”, bukan “tiap 15 menit dari sekarang”. Anda menyimpan pukul 12.03 dan eksekusi berikutnya pukul 12.15. Dengan basis bukan wildcard, 5/15 berarti “mulai dari menit 5, lalu tiap 15 menit”: menit 5, 20, 35, 50.
Nama bulan dan hari
Tulis bulan dan hari sebagai nama, tidak peka huruf besar/kecil:
0 0 1 JAN,APR,JUL,OCT * # hari pertama tiap kuartal
0 9 * * MON-FRI # hari kerja pukul 9 pagi
0 17 * * FRI # Jumat pukul 5 sore
Nama lebih enak dibaca saat code review; bentuk numerik sedikit lebih portabel. Pilih satu gaya per proyek.
Macro non-standar: @reboot, @daily, dan kawan-kawan
Sebagian besar implementasi cron menerima enam macro pintas:
| Macro | Diperluas menjadi | Arti |
|---|---|---|
@yearly / @annually | 0 0 1 1 * | sekali setahun, 1 Januari tengah malam |
@monthly | 0 0 1 * * | tanggal 1 tiap bulan tengah malam |
@weekly | 0 0 * * 0 | tiap Minggu tengah malam |
@daily / @midnight | 0 0 * * * | tiap hari tengah malam |
@hourly | 0 * * * * | tepat di awal tiap jam |
@reboot | (khusus) | sekali saat daemon cron mulai jalan |
Macro ini non-standar: vixie cron dan cronie mendukungnya, tetapi Kubernetes CronJob, GitHub Actions, dan AWS EventBridge tidak. Untuk ekspresi portabel, tulis bentuk lima-kolom. @reboot jarang bekerja di kontainer karena daemon cron biasanya bukan proses init.
50+ Ekspresi Cron Siap Salin (Dikelompokkan per Kasus Penggunaan)
Tabel Referensi Cepat mencakup kasus umum. Bagian ini menggali enam kelompok dengan contoh job cron yang lebih padat.
Setiap N menit
* * * * * # tiap menit
*/2 * * * * # tiap 2 menit
*/5 * * * * # tiap 5 menit — kasus ekspresi cron every 5 minutes
*/10 * * * * # tiap 10 menit
*/15 * * * * # tiap 15 menit
*/30 * * * * # tiap 30 menit
0,30 * * * * # menit 0 dan 30 secara eksplisit (sama dengan */30)
*/45 * * * * # PERINGATAN: hanya dipicu di menit 0 dan 45, lalu wrap
*/45 adalah jebakan klasik. Rentang menit 0-59, sehingga ekspresi ini berhenti di menit 0 dan 45 lalu wrap di jam berikutnya. Untuk irama 45-menit sungguhan, Anda butuh worker eksternal.
Variasi tiap jam
0 * * * * # tiap jam di menit :00
30 * * * * # tiap jam di menit :30
0 */2 * * * # tiap 2 jam, jam genap
0 */6 * * * # tiap 6 jam
0 */12 * * * # dua kali sehari pukul 00.00 dan 12.00
15 */2 * * * # tiap 2 jam, geser 15 menit (hindari lonjakan :00)
Harian pada waktu tertentu
0 0 * * * # tengah malam (= @daily / @midnight)
30 2 * * * # 02.30 — jendela batch trafik rendah
0 9 * * * # 09.00
45 23 * * * # 23.45 — rollup akhir hari
0 9,12,17 * * * # tiga kali sehari
0 9-17 * * * # tiap jam dari 09.00 hingga 17.00
Jadwal mingguan
0 9 * * 1-5 # hari kerja pukul 9 pagi
0 9 * * 0,6 # akhir pekan pukul 9 pagi
0 18 * * 5 # Jumat pukul 6 sore
0 0 * * 0 # Minggu tengah malam (= @weekly)
0 9 * * MON,WED,FRI # Sen/Rab/Jum pukul 9 pagi
*/30 9-17 * * 1-5 # tiap 30 menit, jam kerja, hari kerja
Bulanan dan kuartalan
0 0 1 * * # tanggal 1 tengah malam (= @monthly)
0 0 15 * * # tanggal 15 — jendela payroll
0 0 1,15 * * # tanggal 1 dan 15 — semi-bulanan
0 0 1 */3 * # kuartalan: tanggal 1 Jan, Apr, Jul, Okt
0 0 1 JAN,APR,JUL,OCT * # sama, nama bulan
0 0 28-31 * * # beberapa tanggal terakhir — pasangkan dengan wrapper cek tanggal
Tanggal terakhir tiap bulan tidak punya ekspresi POSIX bawaan. Jalankan wrapper yang memeriksa date -d tomorrow +%d = 01, atau gunakan scheduler dengan dukungan native (Quartz punya L; Kubernetes tidak).
Tahunan dan pintasan macro
0 0 1 1 * # 1 Januari tengah malam (= @yearly / @annually)
0 0 25 12 * # Natal tengah malam
@yearly # = 0 0 1 1 *
@monthly # = 0 0 1 * *
@weekly # = 0 0 * * 0
@daily # = 0 0 * * *
@hourly # = 0 * * * *
@reboot # khusus: sekali saat daemon mulai (hanya vixie cron)
Tempel ekspresi mana pun ke Generator Crontab untuk melihat pratinjau lima eksekusi berikutnya. Itu uji asap (smoke test) termurah sebelum deploy.
Cron vs systemd Timer vs Scheduler Cloud: Matriks Keputusan
Cron adalah pilihan default, bukan selalu pilihan terbaik. Perbandingan tujuh scheduler paling umum berikut berguna untuk keputusan cron vs systemd timer, Kubernetes CronJob vs Vercel cron job, atau migrasi dari crontab ke layanan cloud terkelola.
| Fitur | vixie cron | systemd timer | K8s CronJob | GHA schedule | AWS EventBridge | Vercel Cron | Cloudflare Workers |
|---|---|---|---|---|---|---|---|
| Sintaks kolom | 5 kolom POSIX | spesifikasi OnCalendar | 5 kolom POSIX + timeZone | 5 kolom POSIX | 6 kolom Quartz dengan ? | 5 kolom POSIX | 5 kolom POSIX |
| Interval minimum | 1 menit | 1 detik | 1 menit | best-effort, ≥15 menit disarankan | 1 menit | 1 menit (paket Pro) | 1 menit |
| Timezone eksplisit | CRON_TZ= | Persistent=true | spec.timeZone (1.27+) | hanya UTC | ScheduleExpressionTimezone | hanya UTC | hanya UTC |
| Pemulihan eksekusi terlewat | tidak (pakai anacron) | ya (Persistent=true) | ya (startingDeadlineSeconds) | tidak | ya | tidak | tidak |
| Retry / backoff | tidak | parsial | ya (backoffLimit) | retry saat gagal | ya | tidak | ya |
| Kontrol konkurensi | tidak (pakai flock) | parsial | ya (concurrencyPolicy) | tidak | tidak | tidak | tidak |
Dukungan @reboot | ya | ya (via OnBootSec=) | tidak | tidak | tidak | tidak | tidak |
systemd timer: kapan lebih dipilih daripada cron
Di Linux berbasis systemd, timer adalah alternatif serius: sintaks kalender yang mudah dibaca, integrasi journal, pemulihan eksekusi terlewat. Sebuah timer dan service pasangannya:
# daily-report.timer
[Unit]
Description=Run daily report at 9 AM
[Timer]
OnCalendar=*-*-* 09:00:00
Persistent=true
Unit=daily-report.service
[Install]
WantedBy=timers.target
# daily-report.service
[Unit]
Description=Daily report job
[Service]
Type=oneshot
ExecStart=/usr/local/bin/daily-report.sh
User=reporter
Aktifkan dengan systemctl enable --now daily-report.timer. Fitur unggulannya adalah Persistent=true: jika mesin mati pukul 9 pagi, timer akan dipicu segera setelah mesin booting. Vixie cron tidak punya padanan tanpa anacron. Untuk hardening service, lihat security best practices kami.
Kubernetes CronJob
Kubernetes membungkus jadwal POSIX dengan primitif untuk konkurensi, riwayat, dan timezone eksplisit:
apiVersion: batch/v1
kind: CronJob
metadata:
name: nightly-report
spec:
schedule: "0 2 * * *"
timeZone: "America/New_York" # Kubernetes 1.27+
concurrencyPolicy: Forbid # jangan pernah jalankan dua sekaligus
startingDeadlineSeconds: 300 # lewati jika tertunda >5 menit
jobTemplate:
spec:
backoffLimit: 2
template:
spec:
restartPolicy: OnFailure
containers:
- name: reporter
image: reporter:1.4.0
command: ["/usr/local/bin/report.sh"]
concurrencyPolicy: Forbid adalah padanan flock Anda. Tanpa ini, job yang berjalan lama akan menumpuk di atas penggantinya. Lihat referensi field untuk semua tombol pengaturan.
Catatan penting jadwal GitHub Actions
GitHub Actions menerima cron POSIX lima-kolom standar:
on:
schedule:
- cron: '0 9 * * 1-5' # hari kerja pukul 9 pagi UTC
Sifatnya best-effort: di bawah beban tinggi pada runner GitHub, job bisa terlambat beberapa menit atau dilewati sama sekali. Hindari interval di bawah lima belas menit. Tidak ada pengaturan timezone, selalu UTC.
AWS EventBridge: enam kolom gaya Quartz
AWS EventBridge memakai cron rasa Quartz dengan enam kolom dan ? wajib di salah satu slot hari:
cron(0 9 * * ? *)
Urutan kolom: Menit Jam Hari-bulan Bulan Hari-minggu Tahun. Salah satu kolom hari harus ? ketika kolom lain dibatasi (cara Quartz menyelesaikan ambiguitas OR pada POSIX). Salinan langsung dari crontab Linux akan gagal validasi.
Vercel Cron, Cloudflare Workers, Render Cron Jobs
Platform serverless baru menyeragamkan ke POSIX lima-kolom. Job cron Vercel ditaruh di vercel.json sebagai { "crons": [{ "path": "/api/cron/nightly", "schedule": "0 2 * * *" }] }. Cloudflare Workers Cron Trigger memakai wrangler.toml:
[triggers]
crons = ["*/15 * * * *", "0 9 * * 1-5"]
Render memakai render.yaml. Ketiganya berjalan di UTC tanpa override timezone per-jadwal; rancang dalam UTC sejak awal.
7 Jebakan Debug Cron (Dan Cara Menangkapnya)
Sebagian besar laporan “job cron saya tidak jalan” punya salah satu dari tujuh akar masalah. Telusuri daftar ini sebelum menyalahkan scheduler.
Jebakan 1: PATH minimal
Cron menjalankan job dengan $PATH minimal, biasanya /usr/bin:/bin. Shell interaktif Anda punya /usr/local/bin, ~/.cargo/bin, dan selusin entri .bashrc. Tidak satu pun tersedia di cron. Inilah masalah cron debugging path environment nomor satu.
Gejala: node: command not found. Solusi: setel PATH di awal crontab, atau pakai path absolut.
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin
*/15 * * * * /usr/local/bin/poll-api.sh
0 9 * * * /home/deploy/.cargo/bin/my-rust-cli
Jebakan 2: stdout dan stderr hilang diam-diam
Secara default, output cron pergi ke mail spool yang tidak dibaca siapa pun. Job gagal tanpa suara. Redirect kedua stream:
*/15 * * * * /usr/local/bin/job.sh >> /var/log/job.log 2>&1
Untuk output JSON, pipakan melalui jq; untuk ekstraksi baris log, lihat cheat sheet regex kami. Untuk systemd timer, journalctl -u your-timer.service menangkap output.
Jebakan 3: Perbedaan timezone (timezone drift) antara dev dan prod
Anda menulis 0 9 * * * di laptop di New York, mengharapkan pukul 9 pagi waktu Timur. Server berjalan di UTC. Cron dipicu pukul 9 pagi UTC, yaitu 4 pagi waktu Timur, sebelum siapa pun menyadarinya. Solusi: setel server ke UTC dan tulis jadwal dalam UTC, atau kunci timezone secara eksplisit.
CRON_TZ=America/New_York
0 9 * * * /usr/local/bin/morning-report.sh
CRON_TZ bekerja di vixie cron 3.0+; Kubernetes 1.27+ punya spec.timeZone; AWS EventBridge punya ScheduleExpressionTimezone; GitHub Actions selalu UTC. Untuk UTC, DST, dan matematika epoch, lihat panduan Unix timestamp kami.
Jebakan 4: % tanpa escape dalam perintah
Cron memperlakukan % tanpa escape sebagai newline; sisa baris masuk ke perintah sebagai stdin. Jadi date +"%Y-%m-%d" rusak. Escape setiap % menjadi \%, atau pindahkan logika ke dalam skrip:
0 0 * * * echo "Run at $(date +"\%Y-\%m-\%d")" >> /tmp/log
Jebakan 5: Eksekusi yang saling tumpang tindih
Job */5 * * * * yang sesekali memakan waktu tujuh menit akan memulai instance berikutnya sebelum yang sebelumnya selesai. Dua salinan berebut baris yang sama, file lock yang sama, dan kuota API yang sama. Serialkan dengan flock:
*/5 * * * * flock -n /tmp/job.lock /usr/local/bin/job.sh
-n langsung keluar jika lock sedang dipegang. Untuk Kubernetes, setel concurrencyPolicy: Forbid. Izin file lock penting; lihat security best practices.
Jebakan 6: @reboot di kontainer
@reboot berjalan sekali ketika daemon cron mulai. Di VM, itu sama dengan boot. Di kontainer, daemon cron biasanya bukan PID 1 dan mungkin tidak berjalan sama sekali. Jangan pakai @reboot di kontainer; taruh logika “jalankan sekali saat boot” di entrypoint atau init container.
Jebakan 7: Semantik OR hari-bulan / hari-minggu POSIX
Jebakan cron paling mahal. Aturan POSIX: ketika hari-bulan dan hari-minggu sama-sama dibatasi (tidak ada yang *), jadwal dipicu ketika salah satu cocok.
0 0 1 * 5 terlihat seperti “tengah malam pada tanggal 1, hanya jika Jumat”, tetapi dipicu pada tanggal 1 dan setiap Jumat: enam sampai sepuluh eksekusi ekstra per bulan.
# SALAH: terlihat seperti "tanggal 1 tiap bulan, hanya jika Jumat"
0 0 1 * 5
# BENAR: pilih satu batasan
0 0 1 * * # setiap tanggal 1
0 0 * * 5 # setiap Jumat
# Semantik AND butuh wrapper
0 0 1-7 * 5 [ "$(date +\%u)" = "5" ] && /script # hanya Jumat pertama
Tempel ekspresi yang mencurigakan ke Generator Crontab; pratinjau eksekusi berikutnya membuat jebakan OR ini terlihat jelas.
Scheduler Modern: Kapan TIDAK Memakai Cron
Cron tepat untuk “jalankan perintah ini kira-kira pada waktu ini, dengan irama tetap”. Cron salah untuk beberapa masalah serupa:
- Workflow dengan dependensi (jalankan A, lalu B jika A sukses): pakai Airflow, Prefect, atau Dagster.
- Retry, backoff eksponensial, dead-letter queue: pakai Temporal, AWS Step Functions, atau Sidekiq.
- Interval di bawah satu menit: worker hidup-lama yang tidur di antara iterasi.
- Waktu presisi detik: daemon khusus; scheduler terkelola menolak menjamin waktu eksak.
- Pekerjaan berbasis event: webhook, antrean pesan, stream change-data-capture.
Cron tidak menghilang. Airflow, Step Functions, dan Sidekiq semuanya menerima ekspresi cron sebagai pintu masuk workflow mereka. Tata bahasa lima-kolom tetap dapat dipakai ulang.
Referensi Field Kubernetes CronJob
Matriks keputusan di atas menampilkan CronJob minimal. Referensi field lengkap untuk sintaks kubernetes cronjob:
| Field | Default | Fungsi |
|---|---|---|
schedule | wajib | ekspresi cron POSIX 5 kolom |
timeZone | TZ controller | timezone eksplisit (1.27+); pakai nama IANA |
concurrencyPolicy | Allow | Forbid melewati eksekusi baru saat yang sebelumnya aktif; Replace membatalkannya |
startingDeadlineSeconds | tidak terbatas | lewati jika tertunda lebih lama dari ini |
successfulJobsHistoryLimit | 3 | jumlah Job sukses yang disimpan |
failedJobsHistoryLimit | 1 | jumlah Job gagal yang disimpan |
suspend | false | jeda tanpa menghapus |
backoffLimit | 6 | retry Pod sebelum Job ditandai Failed |
activeDeadlineSeconds | tidak diset | batas keras runtime Pod |
ttlSecondsAfterFinished | tidak diset | hapus Job otomatis setelah sekian detik |
Dua kesalahan umum: lupa timeZone membuat jadwal mengikuti timezone host kube-controller-manager (tidak terduga di Kubernetes terkelola); pada jadwal satu-menit, default successfulJobsHistoryLimit: 3 menumpuk tiga objek Job per menit kecuali ttlSecondsAfterFinished diset.
Padanan Cron Lintas Platform
macOS launchd. Apple merekomendasikan launchd daripada cron. Job launchd adalah file .plist di ~/Library/LaunchAgents/:
<plist version="1.0"><dict>
<key>Label</key><string>com.example.daily</string>
<key>ProgramArguments</key><array><string>/usr/local/bin/daily.sh</string></array>
<key>StartCalendarInterval</key>
<dict><key>Hour</key><integer>9</integer><key>Minute</key><integer>0</integer></dict>
</dict></plist>
Muat dengan launchctl load ~/Library/LaunchAgents/com.example.daily.plist. Tidak seperti cron, launchd mengejar eksekusi yang terlewat setelah sleep/wake.
Windows Task Scheduler memakai schtasks:
schtasks /create /tn "DailyReport" /tr "C:\scripts\report.bat" /sc DAILY /st 09:00
schtasks /create /tn "EveryFifteen" /tr "C:\scripts\poll.bat" /sc MINUTE /mo 15
Di WSL, cron Linux native berfungsi tetapi berhenti ketika sesi berakhir; pakai Task Scheduler untuk meluncurkan job WSL yang selalu menyala.
Cron di kontainer Docker. Sebagian besar image ramping (alpine, debian-slim, distroless) tidak dikirim dengan daemon cron. Pasang cronie atau busybox-cron dan jalankan sebagai PID 1 dengan tini atau s6-overlay. Hampir selalu lebih baik pakai Kubernetes CronJob saja.
Tips dan Pola Lanjutan
Hari terakhir bulan
Cron tidak punya operator “hari terakhir” native. Jalankan tiap hari di rentang 28-31 dan periksa apakah besok adalah tanggal 1:
0 23 28-31 * * [ "$(date -d tomorrow +\%d)" = "01" ] && /usr/local/bin/eom.sh
Hari ke-N dalam minggu di bulan tertentu
“Senin pertama” memakai pola wrapper yang sama; batasi ke hari 1-7, lalu periksa hari-minggu:
0 9 1-7 * * [ "$(date +\%u)" = "1" ] && /usr/local/bin/first-monday.sh
Untuk “Jumat terakhir”, pakai hari 25-31 plus cek hari-minggu.
Offset acak untuk menyebar beban
Ketika banyak mesin menjalankan cron yang sama, 0 0 * * * menghasilkan thundering herd pada tengah malam UTC. Taburkan delay acak:
RANDOM_DELAY=10 # cronie / anacron, dalam menit
0 0 * * * /usr/local/bin/job.sh
0 0 * * * sleep $((RANDOM \% 600)); /usr/local/bin/job.sh # portabel
Monitoring detak jantung (heartbeat)
Cron gagal tanpa suara. Pola dead-man’s-switch: job melakukan ping ke layanan monitoring setelah tiap eksekusi sukses; layanan memberi peringatan ketika ping yang diharapkan tidak tiba. Healthchecks.io, Cronitor, dan Dead Man’s Snitch menawarkan paket gratis.
*/15 * * * * /usr/local/bin/job.sh && curl -fsS --retry 3 https://hc-ping.com/your-uuid
Untuk logika monitoring yang bercabang berdasarkan kode respons (200 sehat, 429 kena rate-limit, 503 degraded), lihat cheat sheet kode status HTTP kami.
Idempotensi adalah properti job, bukan scheduler
Cron tidak punya retry, pemulihan eksekusi terlewat, maupun kontrol konkurensi. Perbaikan paling andal adalah membuat job-nya sendiri aman untuk dijalankan berkali-kali. Alih-alih “kirim laporan hari ini pukul 9 pagi”, rancang sebagai “kirim laporan hari ini jika belum terkirim”. Dengan begitu, eksekusi terlewat, duplikat, dan kejar-kejaran manual akan konvergen ke state yang sama.
FAQ
Apakah */5 * * * * benar-benar setiap 5 menit?
Hampir — */5 * * * * berjangkar pada menit 0, bukan “tiap 5 menit dari sekarang”, lalu dipicu di menit 0, 5, 10, …, 55 tiap jam. Step */N relatif terhadap nilai terkecil kolom, bukan waktu sekarang. Simpan pukul 12.03 dan eksekusi berikutnya pukul 12.05, bukan 12.08.
Apa arti 0 0 * * * dalam cron?
0 0 * * * berarti setiap hari pada tengah malam (00.00) di timezone lokal server. Kolom: menit 0, jam 0, hari-bulan apa pun, bulan apa pun, hari-minggu apa pun. Setara dengan macro @daily atau @midnight. Untuk mengunci timezone, tambahkan CRON_TZ=America/New_York di awal crontab.
Bagaimana menjalankan job cron tiap 30 detik?
Tidak bisa dengan cron POSIX standar; granularitas minimum adalah satu menit. Tiga akal-akalan: dua job berselang-seling pada * * * * * dengan sleep 30 && di salah satunya; systemd timer dengan OnCalendar=*:*:0/30; atau worker hidup-lama yang tidur di antara iterasi. Yang terakhir biasanya yang paling tepat.
Timezone apa yang dipakai cron secara default?
Timezone sistem lokal server (/etc/timezone atau variabel environment TZ). Cron pukul 9 pagi di server UTC akan dipicu pukul 4 pagi waktu Timur AS. Solusi: setel CRON_TZ= di awal crontab, atau setel server ke UTC dan rancang jadwal dalam UTC. GitHub Actions selalu UTC; Kubernetes 1.27+ mendukung spec.timeZone.
Kenapa job cron saya tidak berjalan?
Jika tugas cron Anda tidak berjalan, periksa berurutan: apakah daemon cron menyala (systemctl status cron); apakah $PATH diset di crontab; apakah stderr ditangkap (>> log 2>&1); apakah crontab user termuat (crontab -l); apakah % di-escape dalam perintah; apakah timezone sesuai harapan. Sebagian besar laporan “tidak jalan” jatuh ke item kedua atau ketiga.
Apakah sintaks Kubernetes CronJob sama dengan cron Linux?
Ya untuk kolom schedule; keduanya memakai cron POSIX lima-kolom. Kubernetes menambah spec.timeZone (1.27+), concurrencyPolicy untuk mengatur tumpang tindih, startingDeadlineSeconds untuk pemulihan eksekusi terlewat, dan suspend: true untuk jeda. Cron Linux tidak punya satupun; gunakan flock dan anacron sebagai gantinya.
Apa beda @reboot dengan @daily?
@daily adalah macro untuk 0 0 * * *, yaitu tiap hari tengah malam pada jadwal tetap. @reboot berjalan sekali ketika daemon cron mulai, tanpa jadwal berulang. @reboot didukung oleh vixie cron dan cronie tetapi tidak oleh Kubernetes CronJob, GitHub Actions, atau AWS EventBridge. Di kontainer, @reboot jarang terpicu.
Apa perbedaan antara cron dan crontab?
cron adalah daemon latar belakang yang menjalankan tugas terjadwal; crontab adalah file yang mendaftarkan tugas-tugas tersebut (dan perintah crontab untuk mengeditnya). Daemon membaca crontab setiap pengguna secara berkala dan menjalankan perintah yang waktu eksekusinya cocok dengan ekspresi cron. Singkatnya: cron adalah mesin, crontab adalah resep.