Yayın tarihi · 7 dk okuma
Cron İfadeleri Sıfırdan: Görsel Rehber
5 alanlı POSIX cron syntax, özel karakterler, step değerleri, Quartz uzantıları, AWS cron farkları ve crontab'a doğrudan yapıştırabileceğiniz bir düzine örnekle cron ifadesi nedir sorusunun tam cevabı.
Cron neden hâlâ her yerde?
Cron'u 1979'da Brian Kernighan, Version 7 Unix için yazdı. Bugün çoğu Linux sisteminde gördüğümüz sürüm — 1987'de Paul Vixie'nin yazdığı Vixie cron — environment değişkenleri, kullanıcı bazlı crontab ve @reboot kısayolu gibi şeyler ekledi ama 5 alanlı zaman formatına neredeyse hiç dokunmadı. World Wide Web'den önce tasarlanmış bir syntax'ın 2026'da hâlâ Kubernetes manifest'lerine, GitHub Actions workflow'larına, AWS EventBridge kurallarına ve Spring @Scheduled anotasyonlarına yapıştırılıyor olmasının sebebi bu istikrar.
Cron'u sadece Stack Overflow'dan satır kopyalayarak öğrenirseniz, er ya da geç beklemediğiniz bir şey yapar: günlük backup'ınız her dakika tetiklenir, hafta sonu işiniz Salı günü çalışır, yaz saati geçişinde job tamamen atlanır. Bu rehberde syntax'ı sıfırdan kuracağız ve sonra herhangi bir ifadenin şeklini bir bakışta tanıyabilmenize yetecek kadar örnek göreceğiz.
5 alanlı format
POSIX crontab satırı: önce schedule, sonra komut. Schedule tam olarak beş tane boşlukla ayrılmış alandan oluşur — minute, hour, day of month, month, day of week. Her alan sayı, liste, aralık, step veya * (wildcard) kabul eder.
* * * * * çalıştırılacak-komut
┬ ┬ ┬ ┬ ┬
│ │ │ │ │
│ │ │ │ └─── haftanın günü (0-6, Pazar = 0; çoğu cron'da 7 de Pazar)
│ │ │ └───── ay (1-12, ya da JAN-DEC)
│ │ └─────── ayın günü (1-31)
│ └───────── saat (0-23)
└─────────── dakika (0-59)Özel karakterler: * , - / ve arkadaşları
Klasik cron'da işin neredeyse tamamını beş karakter halleder. Her birinin ne anlama geldiğini öğrenirseniz çoğu ifade düz cümle gibi okunmaya başlar.
- * — alandaki tüm değerler. Minute alanında * "her dakika" demek.
- , — ayrık değer listesi. Minute alanında 0,15,30,45 saatte dört sabit dakika demek.
- - — kapsayıcı aralık. Day-of-week alanında 1-5 Pazartesi'den Cuma'ya demek.
- / — step değeri, range/step veya */step şeklinde. Minute alanında */10, "0'dan başlayarak 10 dakikada bir" demek.
- L, W, # — Quartz uzantıları, POSIX'in parçası değil. L = son, W = en yakın hafta içi, # = ayın n'inci günü. Aşağıda detayı var.
0,30 * * * * her saat :00 ve :30'da
*/5 * * * * her 5 dakikada bir (0, 5, 10, 15 ...)
0 9-17 * * 1-5 Pzt-Cum, 09:00-17:00 arası her saat başı
0 0 1,15 * * her ayın 1'i ve 15'i gece yarısı
15 14 * * 0 her Pazar 14:15Step değeri sandığınız şey değil
Step operatörü / her zaman bir aralığa karşı çalışır — aralık örtük olsa bile. Minute alanında */15 aslında 0-59/15'in kısaltması ve 0, 15, 30, 45 dakikalarında çalışır. Bu yüzden minute alanındaki */7, "şu andan itibaren her 7 dakikada bir" DEMEZ; "0 ile 59 arasındaki 7'nin katları" demektir, yani 0, 7, 14, 21, 28, 35, 42, 49, 56 ve sonra saat dönmeden önce 4 dakikalık bir boşluk. Gerçek anlamda dönen bir interval gerekiyorsa systemd timer'ın OnUnitActiveSec özelliği veya bir job runner daha doğru tercih.
Step'ler aralığın ortasından da başlayabilir. Minute alanında 5-59/10 ifadesi 5, 15, 25, 35, 45, 55'te tetiklenir. Asimetrik bir schedule istediğinizde devasa virgül listesi yazmak yerine range ile step'i birleştirin.
*/15 * * * * 00, 15, 30, 45 (iyi)
*/7 * * * * 00, 07, 14, 21, 28, 35, 42, 49, 56, sonra 4 dk boşluk (muhtemelen istediğiniz değil)
5-59/10 * * * * 05, 15, 25, 35, 45, 55
0 */4 * * * 00:00, 04:00, 08:00, 12:00, 16:00, 20:00Day-of-month ile day-of-week: OR kuralı
Cron'un en bilinen tuzağı: hem day-of-month hem day-of-week kısıtlandığında (ikisi de * değilse) Vixie cron bunları VE değil VEYA olarak yorumlar. Yani 0 0 13 * 5 satırı, hem her ayın 13'ünde hem de her Cuma gece yarısı çalışır — sadece 13'üne denk gelen Cuma'da değil. VE davranışını istiyorsanız iki alandan sadece birini kısıtlayıp diğerini script içinde filtreleyin, ya da Quartz gibi ? placeholder'ını destekleyen bir scheduler kullanın.
0 0 13 * 5 ayın 13'ü VEYA her Cuma gece yarısı (Vixie cron OR kuralı)
0 0 * * 5 her Cuma gece yarısı
0 0 13 * * her ayın 13'ünde gece yarısı
# Quartz: 0 0 0 13 * 5 ? tam olarak 13'üne denk gelen CumaYapıştır-çalıştır 10 cron örneği
Bu tabloyu monitörünüzün yanına yapıştırın. Production'da yazacağınız cron satırlarının çoğu, bu örneklerin küçük varyasyonlarıdır.
* * * * * her dakika
0 * * * * her saat başı (xx:00)
*/15 * * * * her 15 dakikada bir
0 0 * * * her gün gece yarısı (sunucu local time)
0 9 * * 1-5 hafta içi 09:00
30 14 * * 1-5 hafta içi 14:30
0 9 * * 1 her Pazartesi 09:00
0 22 * * 0 her Pazar 22:00
0 0 1 * * her ayın 1'i gece yarısı
0 0 1 1 * 1 Ocak gece yarısı
0 3 * * 6 her Cumartesi 03:00 (klasik backup penceresi)
*/5 9-17 * * 1-5 Pzt-Cum mesai saatlerinde 5 dakikada birİsimli kısayollar
Vixie cron, GNU mcron ve türevlerinin çoğu @ ile başlayan birkaç alias'ı kabul eder. Beş alanlı karşılıklarına göre hem daha okunaklı hem de typo yapması daha zor.
@yearly karşılığı 0 0 1 1 * (@annually de aynı)
@monthly karşılığı 0 0 1 * *
@weekly karşılığı 0 0 * * 0
@daily karşılığı 0 0 * * * (@midnight de aynı)
@hourly karşılığı 0 * * * *
@reboot sistem açılışında bir kez çalıştırırQuartz: 6 ve 7 alanlı kuzeni
Java tarafındaki scheduler'lar — Quartz, Spring'in cron = ile kullandığı @Scheduled, bazı cloud platformları — farklı bir lehçe konuşur. Quartz başa bir saniye alanı ekler, sona da opsiyonel bir yıl alanı koyar; toplam 6 veya 7 alan eder. Ek olarak L (last), W (nearest weekday), # (nth weekday) ve "day-of-month ile day-of-week'ten sadece birini ayarladım" anlamına gelen ? placeholder'ını destekler.
Bir Quartz ifadesini olduğu gibi Linux crontab'ına yapıştırırsanız sessizce yanlış parse edilir; çünkü baştaki 0, Vixie cron için sıradan bir minute değeri gibi görünür. Dosyayı kaydetmeden önce hangi lehçeyi yorumlayacağınızı mutlaka bilin.
Quartz alanları: saniye dakika saat ayın-günü ay haftanın-günü [yıl]
0 0 12 * * ? her gün öğlen 12:00
0 15 10 ? * MON-FRI hafta içi 10:15
0 0 0 L * ? her ayın son günü gece yarısı
0 0 0 LW * ? her ayın son hafta içi günü
0 0 9 ? * 2#1 her ayın ilk Pazartesi'si 09:00
0 0 9 ? * 6#3 her ayın üçüncü Cuma'sı 09:00
0 0 0 1 * ? 2026 her ayın 1'i gece yarısı, sadece 2026'daAWS: rate ve cron syntax farkları
EventBridge, CloudWatch Events ve Lambda, Quartz'a benzer ama iki önemli farkı olan bir cron syntax'ı kullanır. Saniye alanı yoktur (7 değil 6 alan) ve day-of-month ile day-of-week'ten birini mutlaka ? olarak vermeniz gerekir — ikisini birden * yapamazsınız. AWS ayrıca basit interval'ler için rate(value unit) sunar, bu da OR tuzağını tamamen ortadan kaldırır.
AWS cron alanları: minute hour day-of-month month day-of-week year
cron(0 12 * * ? *) her gün UTC 12:00
cron(0/15 * * * ? *) her 15 dakikada bir
cron(0 9 ? * MON-FRI *) hafta içi UTC 09:00
cron(0 0 1 * ? *) her ayın 1'i UTC gece yarısı
rate(5 minutes) her 5 dakikada bir
rate(1 hour) her saat başı
rate(7 days) kural oluşturulduğu andan itibaren 7 günde birTimezone, DST ve 02:30'da kırılan şeyler
Vixie cron sistem timezone'una uyar (TZ environment değişkeni veya /etc/localtime'ın işaret ettiği yer). Yaz saati uygulamasında ileri atlanan saat içine düşen herhangi bir job sessizce skip edilir; geri alındığında tekrar eden saat içine düşen job ise bazı sürümlerde iki kez, bazılarında bir kez çalışır. Güvenli iki default: cron'u UTC'de çalıştırın veya 01:00-04:00 penceresinin dışına schedule edin.
Cloud scheduler'lar farklı davranır. EventBridge her zaman UTC'dir. Kubernetes CronJob, v1.27 ile gelen spec.timeZone alanına saygı gösterir. Quartz, CronTrigger'a timezone vermezseniz JVM default'unu kullanır. Hangisini configure ediyorsanız bir kere dokümanını okuyun; bir öncekinin kuralının geçerli olduğunu varsaymayın.
Tetiklenmeyen ifadeyi debug etmek
On vakanın dokuzunda ifade aslında doğrudur, environment yanlıştır. Schedule'ı suçlamadan önce şu listeden geçin.
- Cron daemon log'una bakın: Debian/Ubuntu'da grep CRON /var/log/syslog, systemd host'larda journalctl -u cron. Log, cron'un gerçekten çalıştırdığı komut satırını gösterir.
- Doğru kullanıcı mı? crontab -l flagsız komut SİZİN crontab'ınızı gösterir; aradığınız satır /etc/crontab, /etc/cron.d/* veya başka bir kullanıcının crontab'ında olabilir.
- PATH'i kontrol edin. Cron minimal PATH ile çalışır (genellikle /usr/bin:/bin). Mutlak path kullanın veya crontab'ın başına PATH= ekleyin.
- Shell'i kontrol edin. Cron /bin/sh kullanır, sizin login shell'inizi değil. Bash'e özgü bir şey (process substitution, [[ )) kullanıyorsanız bash -c sarmalayıcısı şart.
- Output'u yönlendirin. > /var/log/myjob.log 2>&1 olmadan başarısız job lokal olarak root'a mail atar ve siz hiç görmezsiniz.
- Timezone'u doğrulayın. Job içinde date && date -u logu ikisini birden gösterir. Schedule'ın varsaydığıyla uyuşmuyorsa bug oradadır.
# Daha güvenli bir cron satırı:
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=""
*/5 * * * * /usr/local/bin/sync.sh >> /var/log/sync.log 2>&1Cron'un yanlış araç olduğu durumlar
Cron sabit duvar saatine bağlı schedule'lar için harika, tek host üzerinde tek satırlık job için rakipsiz. Ama şu durumlarda kötü bir tercih: birden çok makine arasında dağıtık koordinasyon (queue, leader-elected scheduler veya concurrencyPolicy: Forbid'li Kubernetes CronJob kullanın); başarısızlıkta retry ve back-off (script'i sarmalayın veya bir workflow engine seçin); dakika altı granularity (systemd timer veya event-driven trigger); önceki run bitmeden ikincisinin başlamaması gereken job'lar (cron, ilki çalışırken ikincisini memnuniyetle başlatır). Bu sınırı erken görmek, gece 03:00 alarmlarından kurtarır.
Görsel olarak inşa edip doğrulayın
Ayda birkaç cron satırından fazlasını yazıyorsanız, en yüksek kaldıraçlı alışkanlık her ifadeyi commit'lemeden önce bir parser'da kontrol etmektir. Multilities'in /tools/cron-builder aracı 5 veya 6 alanlı bir ifadeyi düz dile çevirir ve sonraki on tetikleme zamanını local timezone'unuzda gösterir; tam olarak day-of-month/day-of-week OR tuzağını ve */7 tarzı step sürprizlerini yakalayan cross-check de bu. Buna bilinen bir referans tarih için sonraki tetikleme zamanını assert eden hızlı bir unit test ekleyin; o noktadan sonra scheduled job'larınız sıkıcı derecede güvenilir olur — zaten istediğimiz tam olarak bu.