Crontab: Linux'ta görev zamanlama örnekleri, sözdizimi ve tipik hatalar
Crontab, cron servisinin komutları çalıştırdığı zamanlama tablosudur. Her satır beş zaman alanından (dakika, saat, ayın günü, ay, haftanın günü) ve bir komuttan oluşur; örneğin */5 * * * * /opt/backup.sh betiği her 5 dakikada bir çalıştırır. Tablo crontab -e ile düzenlenir; sorunların çoğu cron'un kısıtlı ortamından kaynaklanır: tam yollar kullanın ve çıktıyı bir günlük dosyasına yönlendirin.
Cron, Linux'un standart görev zamanlayıcısıdır: cron servisi her dakika zamanlama tablolarını (crontab) okur ve zamanı gelen komutları çalıştırır. Gece yedeklemeleri, geçici dosyaların temizlenmesi, sertifikaların yenilenmesi ve raporların gönderilmesi böyle yapılır. Aşağıda sözdizimi, tipik durumlar için crontab örnekleri ve görevin "sessizce" çalışmamasının nedenleri anlatılıyor.
Crontab nasıl açılır ve düzenlenir
Her kullanıcının kendi tablosu vardır. Bu tablo ile /var/spool/cron içindeki dosyaları doğrudan düzenleyerek değil, crontab komutuyla çalışılır:
| Komut | Ne yapar |
|---|---|
crontab -e | kendi tablonuzu düzenleyicide açar (ilk çalıştırmada düzenleyici seçmenizi ister) |
crontab -l | mevcut tabloyu gösterir |
crontab -r | tabloyu tamamen siler, onay sormaz |
crontab -i -r | onay sorarak siler (Debian/Ubuntu, RHEL) |
sudo crontab -u alice -e | başka bir kullanıcının tablosunu düzenler |
crontab dosya | tabloyu dosyanın içeriğiyle değiştirir |
crontab -e kaydettikten sonra sözdizimini kontrol eder ve crontab: installing new crontab yazar. Bir satırda hata varsa errors in crontab file, can't install mesajı ve yeniden düzenleme önerisi görürsünüz. Servisi yeniden başlatmak gerekmez — değişiklikler otomatik alınır.
-r konusunda dikkatli olun: e ve r tuşları klavyede yan yanadır ve tablonun yedeği yoktur. Yedek tutmak iyi bir alışkanlıktır:
crontab -l > ~/crontab.bak
# geri yüklemek için
crontab ~/crontab.bak
Crontab sözdizimi: beş zaman alanı
Her görev satırı şöyle görünür:
# ┌───────── dakika (0–59)
# │ ┌─────── saat (0–23)
# │ │ ┌───── ayın günü (1–31)
# │ │ │ ┌─── ay (1–12 veya jan–dec)
# │ │ │ │ ┌─ haftanın günü (0–7 veya sun–sat; 0 ve 7 — pazar)
# │ │ │ │ │
* * * * * komut
Her alanda özel karakterler kullanılabilir:
| Karakter | Anlamı | Örnek |
|---|---|---|
* | herhangi bir değer | * * * * * — her dakika |
, | liste | 0 9,18 * * * — 09:00 ve 18:00'de |
- | aralık | 0 9-18 * * * — 9'dan 18'e kadar her saat başı |
/ | adım | */15 * * * * — her 15 dakikada |
Adım, aralıkla birleştirilebilir: 0 8-20/2 * * * — 8'den 20'ye kadar iki saatte bir (8, 10, …, 20). Saat dilimi sistemin saat dilimidir; timedatectl ile kontrol edin.
Her gün için crontab örnekleri
| Zamanlama | Crontab satırı |
|---|---|
| her dakika | * * * * * |
| her 5 dakikada | */5 * * * * |
| her 30 dakikada | */30 * * * * veya 0,30 * * * * |
| her saat başında | 0 * * * * |
| her 6 saatte bir | 0 */6 * * * |
| her gün 03:00'te | 0 3 * * * |
| her gün 23:45'te | 45 23 * * * |
| hafta içi 09:00'da | 0 9 * * 1-5 |
| hafta sonları öğlen | 0 12 * * 6,0 |
| pazartesi 08:30'da | 30 8 * * 1 |
| her ayın 1'inde 00:00'da | 0 0 1 * * |
| çeyrekte bir | 0 0 1 1,4,7,10 * |
| yılda bir, 1 Ocak'ta | 0 0 1 1 * |
| mesai saatlerinde her 10 dakikada | */10 9-18 * * 1-5 |
Tam görev satırı, zamanlama artı komuttur:
# veritabanı yedeği her gece 03:00'te
0 3 * * * /usr/local/bin/db-backup.sh >> /var/log/db-backup.log 2>&1
# pazar günleri 30 günden eski geçici dosyaları temizle
0 4 * * 0 /usr/bin/find /tmp/app -type f -mtime +7 -delete
# siteyi her 5 dakikada kontrol et
*/5 * * * * /usr/bin/curl -fsS https://example.com/health > /dev/null || /usr/local/bin/alert.sh
@reboot, @daily ve diğer özel satırlar
Beş alan yerine kısa bir takma ad da yazılabilir:
| Takma ad | Karşılığı |
|---|---|
@reboot | cron başladığında bir kez (sistem açıldıktan sonra) |
@hourly | 0 * * * * |
@daily / @midnight | 0 0 * * * |
@weekly | 0 0 * * 0 |
@monthly | 0 0 1 * * |
@yearly / @annually | 0 0 1 1 * |
@reboot /home/alice/bin/start-tunnel.sh >> /home/alice/tunnel.log 2>&1
Sürekli çalışması ve çöktüğünde yeniden başlatılması gereken servisler için @reboot zayıf bir çözümdür: bunun yerine Restart=on-failure içeren bir systemd birimi yazın.
Her N saniyede bir görev nasıl çalıştırılır
cron'un en küçük birimi bir dakikadır. Daha sık gerekiyorsa iki yöntem vardır. Birincisi sleep ile kaydırılmış birkaç satır:
* * * * * /opt/check.sh
* * * * * sleep 30; /opt/check.sh
İkincisi, daha doğru olanı, OnUnitActiveSec=30s ile systemd zamanlayıcısıdır. Görev dakikada birden fazla çalışacaksa, bu genellikle cron değil bir daemon veya zamanlayıcının işidir.
Sistem crontab'ı: /etc/crontab ve /etc/cron.d
Kullanıcı tablolarının yanı sıra sistem tabloları da vardır. Formatları farklıdır: zaman ile komut arasında komutun hangi kullanıcı adına çalışacağı yazılır.
# /etc/cron.d/certbot-renew
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
0 */12 * * * root certbot renew --quiet
Nerede ne var:
/etc/crontab— ana sistem tablosu; Debian/Ubuntu'da aşağıdaki dizinlerden de görevler bu tabloyla çalışır./etc/cron.d/— görevleri içeren ayrı dosyalar; paketler tarafından veya Ansible ile eklenmesi kolaydır./etc/cron.hourly/,cron.daily/,cron.weekly/,cron.monthly/— zamanlaması olmayan çalıştırılabilir betikler buraya konur; bunlarırun-parts(veya anacron) çalıştırır.
run-parts tuzağı: Debian ve Ubuntu'da adında nokta olan dosyaları atlar. /etc/cron.daily/ içindeki backup.sh çalışmaz — adını backup yapın. Neyin çalıştırılacağını run-parts --test /etc/cron.daily ile kontrol edebilirsiniz.
/etc/cron.d/ içindeki dosyalar root'a ait olmalı, grup ve diğerleri tarafından yazılamamalı ve bir satır sonu ile bitmelidir — aksi halde cron bunları yok sayar.
cron ortamı: PATH, SHELL ve değişkenler
"Terminalde çalışıyor, cron'da çalışmıyor" durumunun ana nedeni ortamdır. cron komutları /bin/sh ile, .bashrc ve .profile olmadan, minimal bir PATH ile (genellikle /usr/bin:/bin) çalıştırır. Bu yüzden /usr/local/bin içindeki docker, node veya php bulunamayabilir.
Değişkenler tablonun başına yazılabilir:
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=admin@example.com
CRON_TZ=Europe/Istanbul
0 6 * * * cd /srv/app && ./report.sh
MAILTO— görevin çıktısının gideceği adres;MAILTO=""e-postayı kapatır.CRON_TZ— zamanlama için saat dilimi (RHEL/Fedora'daki cronie destekler; Debian sürümündeki cron bu değişkeni desteklemez).- Değişken değerlerinde
$HOME/bingibi genişletme yoktur — yolları tam yazın.
En güvenilir yol, görevde tüm programlar ve dosyalar için mutlak yollar belirtmek, betiklerde ise ilk satıra shebang koymaktır: #!/bin/bash.
cron günlükleri nerede
Cron, görevin çalıştığı olayı günlüğe yazar, ama görevin çıktısını yazmaz:
# Debian/Ubuntu
grep CRON /var/log/syslog
# systemd-journald üzerinden
journalctl -u cron --since today # Debian/Ubuntu
journalctl -u crond --since today # RHEL, Fedora, Rocky
# journald olmayan RHEL
tail -f /var/log/cron
Başlatma satırı kabaca şöyle görünür:
Oct 14 03:00:01 web1 CRON[21544]: (root) CMD (/usr/local/bin/db-backup.sh >> /var/log/db-backup.log 2>&1)
Görevin ne yazdığını ve hangi hatayla düştüğünü görmek için hem stdout'u hem stderr'i bir dosyaya yönlendirin: >> /var/log/job.log 2>&1. Bu yapılmazsa çıktı yerel posta ile gönderilir; posta ajanı kurulu değilse kaybolur (günlükte No MTA installed, discarding output görünür).
cron neden görevi çalıştırmıyor: tipik hatalar
Komut bulunamadı
Belirti: görev günlüğünde command not found. Neden: kısıtlı PATH. Çözüm: programın tam yolunu yazmak (which docker size yolu gösterir) veya tablonun başına PATH= satırı eklemek.
Komutta yüzde işareti
crontab'ta % karakteri satır sonu anlamına gelir: ilk %'den sonraki her şey komuta standart girdi olarak verilir. Bu yüzden dosya adında tarih içeren klasik satır bozulur:
# yanlış — komut ilk % işaretinde kesilir
0 2 * * * tar czf /backup/site-$(date +%F).tar.gz /var/www
# doğru — kaçış karakteri ile
0 2 * * * tar czf /backup/site-$(date +\%F).tar.gz /var/www
Daha kolayı, mantığı bir betiğe taşımaktır: betikte % kaçırılmasına gerek kalmaz.
Betik çalıştırılabilir değil veya satır sonları yanlış
Permission denied hatası, dosyada x biti olmadığı anlamına gelir: chmod +x script.sh çalıştırın ya da açıkça /bin/bash /opt/script.sh yazın. Betik Windows'ta yazıldıysa CRLF satır sonları /bin/bash^M: bad interpreter gibi garip bir hataya yol açar — sed -i 's/\r$//' script.sh veya dos2unix ile düzeltilir.
Göreli yollar ve çalışma dizini
Görev, kullanıcının ev dizininde başlar. Betik ./config.ini dosyasını okuyorsa, onu ~ içinde arar. Komutun önüne cd /srv/app && yazın ya da betik içinde mutlak yollar kullanın.
Ayın günü ve haftanın günü birlikte
İki alan da doluysa, cron her iki alandan herhangi biri eşleştiğinde çalışır, ikisi birden eşleşmek zorunda değildir. 0 9 13 * 5 satırı 13'ünde ve her cuma çalışır; yalnızca 13'ü cuma olan günlerde değil. Doğru koşulu komutun içinde kontrol edin:
0 9 13 * * [ "$(date +\%u)" = 5 ] && /opt/friday13.sh
Görevler üst üste biniyor
Yedekleme, aralıktan daha uzun sürerse bir sonraki başlatma öncekinin üstüne biner. Korumak için flock ile kilit kullanın:
*/10 * * * * /usr/bin/flock -n /tmp/sync.lock /opt/sync.sh
-n bayrağıyla, ilk çalışma hâlâ sürüyorsa ikincisi hemen sonlanır.
cron servisi çalışmıyor
systemctl status cron ile kontrol edin (RHEL'de crond). Minimal imajlarda, örneğin Docker konteynerlerinde, cron servisi hiç yoktur — crontab'taki görevleri çalıştıracak kimse yoktur.
cron görevini nasıl ayıklarsınız
Komutu cron'a mümkün olduğunca benzer bir ortamda çalıştırın:
env -i SHELL=/bin/sh PATH=/usr/bin:/bin HOME=$HOME /bin/sh -c '/opt/backup.sh'
Burada bir hata çıkarsa, cron'da da aynı hata çıkacaktır. Geçici olarak * * * * * zamanlaması koyun, çıktıyı bir dosyaya yönlendirin ve tail -f ile izleyin. Zamanlama ifadesini kontrol etmek için çevrimiçi cron hesaplayıcıları yardımcı olur, ama son sözü sistem günlüğü söyler.
cron'u kimler kullanabilir: cron.allow ve cron.deny
Erişimi /etc/cron.allow ve /etc/cron.deny dosyaları sınırlar. cron.allow varsa, crontab yalnızca içinde adı geçen kullanıcılara açıktır. Yoksa ve cron.deny varsa, listede olanlar hariç herkese açıktır. Yasaklı bir kullanıcı crontab -e çalıştırdığında You (bob) are not allowed to use this program mesajını görür.
Sonuç
Crontab, beş zaman alanı ile komuttan oluşan satırlardır: */5 * * * * her 5 dakikada, 0 3 * * * her gece, 0 9 * * 1-5 hafta içi. Tabloyu crontab -e ile düzenleyin, mutlak yolları kullanın, % işaretini kaçırın, çıktıyı bir günlüğe yazın ve uzun süren görevleri flock ile koruyun. Bu crontab örnekleri çoğu sunucu görevi için yeterlidir; görev zamanlama ve otomasyon kurstaki Linux uygulamalarında ayrıntılı ele alınır.
Sık sorulan sorular
cron ile anacron arasındaki fark nedir?
cron görevleri tam zamanında çalıştırır ve bilgisayar kapalıysa atlar. anacron, günlük, haftalık ve aylık görevlerin açılıştan sonra mutlaka çalışmasını sağlar; bu yüzden dizüstü bilgisayarlar ve masaüstü sistemler için uygundur.
cron mu yoksa systemd zamanlayıcıları mı daha iyi?
cron daha basittir ve hemen hemen her yerde vardır. systemd zamanlayıcıları ise journalctl'de günlük, bağımlılıklar, kaynak sınırlaması ve atlanan çalıştırmalar için Persistent=true seçeneği sunar; bu yüzden modern sunucularda önemli görevler için giderek daha çok tercih edilirler.
Kullanıcının crontab dosyası fiziksel olarak nerede tutulur?
Debian ve Ubuntu'da /var/spool/cron/crontabs/kullanici, RHEL ve Fedora'da /var/spool/cron/kullanici altında. Bu dosyaları doğrudan düzenlemeyin; crontab -e kullanın.
Bir crontab görevini geçici olarak nasıl devre dışı bırakırım?
crontab -e ile satırın başına # koyarak yorum satırı yapın. Kullanıcının tüm görevlerini kapatmak için crontab -l ile tabloyu bir dosyaya kaydedin, sonra crontab -r ile silin.
Bir görevi ayın son gününde nasıl çalıştırırım?
Bunun için ayrı bir alan yoktur. Görevi 28–31 günlerinde çalıştırın ve yarının ayın birinci günü olup olmadığını kontrol edin: 0 23 28-31 * * [ "$(date -d tomorrow +\%d)" = 01 ] && /opt/job.sh.
Bu konu “Linux: с нуля до уверенного администрирования” kursunda uygulamalı olarak ayrıntılı işleniyor.
Kursa git