Cron Görevleri Çalışmıyor: Adım Adım Hata Tespiti ve Çözümü
Hepsini denedik: servisi yeniden başlattık, görevi tekrar ekledik, hatta sunucuyu reboot ettik. Ama cron görevi hala çalışmıyor. Bu durum, sysadmin hayatının en sinir bozucu anlarından biri. Neyse ki cron sorunlarının büyük çoğunluğu aynı birkaç kategoriye giriyor ve sistematik bir yaklaşımla sorunu bulmak düşündüğünden çok daha kolay.
Önce Temel Kontrolleri Yap
Karmaşık debug süreçlerine girmeden önce en basit şeyleri kontrol etmek, saatlerce zaman kazandırır. İlk olarak cron servisinin çalışıp çalışmadığına bak:
# Systemd tabanlı sistemlerde
systemctl status cron
# veya
systemctl status crond
# SysV init tabanlı sistemlerde
service cron status
Servis çalışmıyorsa başlat:
systemctl start cron
systemctl enable cron # Sistem yeniden başladığında otomatik başlasın
Bir de crontab dosyasının gerçekten kaydedilip kaydedilmediğini kontrol et:
crontab -l # Mevcut kullanıcının crontab'ını listele
crontab -l -u www-data # Belirli bir kullanıcının crontab'ını listele
Boş çıktı veya “no crontab for user” mesajı görüyorsan, crontab hiç kaydedilmemiş demektir. Bu aşamada ayrıca /etc/cron.d/, /etc/cron.daily/, /etc/cron.weekly/ gibi sistem genelindeki cron dizinlerini de kontrol et.
Cron Sözdizimi Hataları
Cron sözdizimi hatası, görevin çalışmamasının en yaygın nedenidir. Beş zaman alanını (dakika, saat, gün, ay, haftanın günü) doğru yazmak kritiktir.
# Format: dakika saat gün ay haftanın_günü komut
* * * * * /path/to/script.sh
0 2 * * * /usr/bin/backup.sh
*/5 * * * * /usr/local/bin/monitor.sh
0 9 * * 1-5 /opt/scripts/weekday_task.sh
Yaygın sözdizimi hataları:
- Yanlış aralık kullanımı:
1-5/2yerine1,3,5yazmak gerekirken hatalı format kullanmak - Sıfır ile başlayan değerler: Bazı cron implementasyonlarında
08veya09sekizlik sayı olarak yorumlanabilir - Fazladan boşluk veya tab karakterleri: Alanlar arasında birden fazla boşluk olması
- Eksik PATH tanımı: Komutun tam yolu yerine sadece adının yazılması
Sözdizimini test etmek için online araçlar veya crontab.guru gibi siteler kullanabilirsin. Ama en güvenilir yol terminalden test etmek:
# crontab dosyasını sözdizimi hatası kontrolüyle aç
crontab -e
# Bir sonraki çalışma zamanını hesaplamak için
echo "*/5 * * * *" | awk '{print "Dakika:"$1, "Saat:"$2, "Gun:"$3, "Ay:"$4, "Haftanin gunu:"$5}'
Cron Loglarını Okumak
Cron her çalıştığında (veya çalışmaya çalıştığında) log bırakır. Bu loglar altın değerindedir:
# Debian/Ubuntu sistemlerde
grep CRON /var/log/syslog | tail -50
grep CRON /var/log/syslog | grep -i error
# RHEL/CentOS/Rocky Linux sistemlerde
grep CRON /var/log/cron | tail -50
# Journald kullanan sistemlerde
journalctl -u cron --since "1 hour ago"
journalctl -u crond -f # Canlı takip
Log çıktısında şu satırları arıyorsun:
Jun 15 14:30:01 server CRON[12345]: (root) CMD (/usr/bin/backup.sh)
Jun 15 14:30:01 server CRON[12346]: (CRON) info (No MTA installed, discarding output)
İlk satır görevin tetiklendiğini gösterir. İkincisi ise çıktının nereye gittiği hakkında bilgi verir. Eğer bu satırları hiç göremiyorsan, cron görevi ya tetiklenmiyor ya da log seviyesi çok düşük ayarlanmış demektir.
Loglarda hiçbir şey yoksa, cron daemon’ının loglama yapıp yapmadığını kontrol et:
# /etc/rsyslog.conf veya /etc/rsyslog.d/ dosyalarını kontrol et
grep -i cron /etc/rsyslog.conf
grep -r cron /etc/rsyslog.d/
PATH Problemi: En Sık Yapılan Hata
Bu konu o kadar önemli ki ayrı bir başlık hak ediyor. Cron çalışırken sisteminizin normal PATH değişkenini kullanmaz. Cron’un varsayılan PATH’i son derece kısıtlıdır:
PATH=/usr/bin:/bin
Terminalinde çalışan bir script, cron altında çalışmıyor mu? Büyük ihtimalle PATH sorunudur. Bunu test etmek için:
# Hangi python/python3 kullandığını bul
which python3
# Çıktı: /usr/bin/python3
# Script içinde tam yolu kullan
/usr/bin/python3 /opt/scripts/myscript.py
Bunu çözmek için iki yaklaşım var. Birincisi, crontab dosyasının en başına PATH tanımı eklemek:
# Crontab dosyasının başına ekle
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/custom/bin
0 * * * * /opt/scripts/backup.sh
*/5 * * * * python3 /opt/monitor/check.py
İkincisi, script içine veya komutun başına tam yolları yazmak:
# Crontab'da tam yol kullan
0 2 * * * /usr/bin/python3 /home/admin/scripts/cleanup.py
0 4 * * * /usr/local/bin/node /var/www/scripts/process.js
Çıktıyı Yakalamak ve Hata Ayıklamak
Cron görevi çalışıyor ama beklediğin sonucu vermiyor mu? Çıktıyı bir dosyaya yönlendirerek ne olduğunu görebilirsin:
# Hem standart çıktıyı hem de hataları kaydet
0 2 * * * /usr/bin/backup.sh >> /var/log/backup.log 2>&1
# Sadece hataları kaydet
0 2 * * * /usr/bin/backup.sh > /dev/null 2>> /var/log/backup_errors.log
# Tarih damgasıyla kaydet
0 2 * * * echo "$(date): Backup started" >> /var/log/backup.log && /usr/bin/backup.sh >> /var/log/backup.log 2>&1
2>&1 ne anlama geliyor:
>: Standart çıktıyı yönlendir2>: Standart hata çıktısını yönlendir&1: Standart çıktının gittiği yere yönlendir>>: Dosyaya ekle (üzerine yazma)
Bir script’in cron ortamında nasıl davranacağını önceden test etmek için cron ortamını simüle edebilirsin:
# Cron ortamını simüle ederek test et
env -i HOME=/root LOGNAME=root PATH=/usr/bin:/bin SHELL=/bin/sh /usr/bin/backup.sh
# Veya su ile belirli bir kullanıcı olarak test et
su -s /bin/sh www-data -c "/var/www/scripts/task.sh"
Kullanıcı İzinleri ve Dosya Yetkileri
Cron görevi doğru kullanıcı altında çalışıyor mu? Bir script root olarak yazılmış ama www-data kullanıcısının crontab’ına eklenmiş olabilir.
# Script'in sahibini ve izinlerini kontrol et
ls -la /opt/scripts/backup.sh
# -rwxr-xr-x 1 root root 1234 Jun 15 10:00 /opt/scripts/backup.sh
# Script çalıştırılabilir mi?
chmod +x /opt/scripts/backup.sh
# Kullanıcının crontab çalıştırma iznini kontrol et
cat /etc/cron.allow # Sadece bu kullanıcılar cron kullanabilir
cat /etc/cron.deny # Bu kullanıcılar cron kullanamaz
İzin kontrol noktaları:
- Script dosyasının çalıştırma izninin olması (
chmod +x) - Script’in eriştiği dosya ve dizinlerin cron kullanıcısı tarafından okunabilir/yazılabilir olması
/etc/cron.allowdosyasının varlığı ve içeriği- SELinux veya AppArmor’un script çalışmasını engelleyip engellemediği
SELinux kullanan sistemlerde cron ile ilgili sorunlar yaygındır:
# SELinux hatalarını kontrol et
ausearch -m avc -ts recent | grep cron
journalctl -xe | grep -i selinux | grep cron
# Geçici olarak SELinux'u permissive moda al (test için)
setenforce 0
# Test ettikten sonra tekrar enforce moda al
setenforce 1
Gerçek Dünya Senaryosu: MySQL Backup Script’i
Bir müşteri, gece 2’de çalışması gereken MySQL backup script’inin hiç çalışmadığını söyledi. Sabah gelince database’in yedeğinin olmadığını fark etmişti. Sorun tespiti şöyle ilerledi:
Önce crontab’a baktık:
crontab -l -u root
# 0 2 * * * /usr/local/bin/mysql_backup.sh
Doğru görünüyordu. Log kontrolü:
grep CRON /var/log/syslog | grep "mysql_backup"
# Hiçbir çıktı yok
Script hiç tetiklenmemişti bile. Servis kontrolü:
systemctl status cron
# ● cron.service - Regular background program processing daemon
# Loaded: loaded (/lib/systemd/system/cron.service; enabled)
# Active: active (running)
Servis çalışıyordu. Sonra dosya iznine baktık:
ls -la /usr/local/bin/mysql_backup.sh
# -rw-r--r-- 1 root root 856 Jun 10 09:15 mysql_backup.sh
Bulunduk! Script’in çalıştırma izni yoktu. chmod +x eklenince sorun çözüldü. Ama bir adım daha ileri gittik ve script’i test ettik:
# Cron ortamında test
env -i HOME=/root LOGNAME=root PATH=/usr/bin:/bin SHELL=/bin/sh /usr/local/bin/mysql_backup.sh
# mysqldump: command not found
İkinci sorun: mysqldump, /usr/bin/ altında değil /usr/local/mysql/bin/ altındaydı. Script’in başına PATH ekledik ve her şey düzeldi.
Crontab Dosyasının Kendisinde Sorun Olabilir
Bazen crontab dosyası bozulmuş veya hatalı karakterler içeriyor olabilir. Bunu kontrol etmek için:
# Raw crontab içeriğini görüntüle
crontab -l | cat -A
# $ işaretleri satır sonlarını göstermeli, ^M Windows satır sonu demek
# Windows satır sonlarını (CRLF) Unix formatına çevir
crontab -l | sed 's/r//' > /tmp/fixed_crontab
crontab /tmp/fixed_crontab
rm /tmp/fixed_crontab
Windows’ta düzenlenen ve sunucuya kopyalanan script’ler sıklıkla bu sorunu taşır. ^M karakterleri cron’un komutu tanımamasına neden olur.
Sistem Zamanı ve Saat Dilimi
Cron görevleri sistem saatine göre çalışır. Sunucu saati yanlışsa, görevler beklediğin zamanda çalışmaz:
# Sistem saatini kontrol et
date
timedatectl status
# Saat dilimini kontrol et
cat /etc/timezone
ls -la /etc/localtime
# NTP senkronizasyonunu kontrol et
timedatectl show | grep NTP
chronyc tracking
ntpq -p
Saat dilimi değişikliği sonrası cron’u yeniden başlatmayı unutma:
# Saat dilimini değiştirdikten sonra
systemctl restart cron
Özellikle cloud ortamlarında, snapshot’tan geri yüklenen veya başka bir bölgeye taşınan sunucularda saat dilimi sorunları sıkça görülür.
/etc/cron.d Dosyalarında Dikkat Edilmesi Gerekenler
Sistem genelindeki cron görevleri için /etc/cron.d/ kullanılır. Bu dosyalar, kullanıcı crontab’larından biraz farklı bir format gerektirir:
# /etc/cron.d/myapp dosyası
# Kullanıcı adı belirtmek ZORUNLU
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# dakika saat gün ay haftanın_günü KULLANICI komut
0 2 * * * root /opt/myapp/scripts/backup.sh >> /var/log/myapp_backup.log 2>&1
*/5 * * * * www-data /var/www/myapp/scripts/health_check.py
Bu dosyalarda sık yapılan hata kullanıcı adını unutmak. Kullanıcı adı olmadan görev sessizce başarısız olur, hiçbir log bırakmaz.
Ayrıca /etc/cron.d/ dosyalarının izinleri önemli. Cron daemon’ı bu dosyaların dünya yazılabilir olmamasını şart koşar:
ls -la /etc/cron.d/
# -rw-r--r-- 1 root root 120 Jun 15 08:00 myapp
# Hatalı izin (cron bu dosyayı yok sayar):
# -rw-rw-rw- 1 root root 120 Jun 15 08:00 myapp
# Düzelt:
chmod 644 /etc/cron.d/myapp
Anacron ile Farkı Anlamak
Sürekli çalışmayan sistemlerde (dizüstü bilgisayarlar, gelişim sunucuları gibi) cron görevi atlanmış olabilir. Bu durumda anacron devreye girer. Eğer /etc/cron.daily/, /etc/cron.weekly/ gibi dizinlerdeki görevler çalışmıyorsa:
# Anacron durumunu kontrol et
systemctl status anacron
# Anacron loglarını kontrol et
journalctl -u anacron
# Manuel olarak çalıştır
anacron -fn -t /etc/anacrontab
# Anacron'un görev zamanlarını kontrol et
cat /var/spool/anacron/cron.daily
Hızlı Hata Ayıklama Kontrol Listesi
Cron sorunu yaşadığında takip edebileceğin sistematik yaklaşım:
Adım 1 – Servis kontrolü:
systemctl status cron || systemctl status crond
Adım 2 – Log kontrolü:
journalctl -u cron --since "24 hours ago" | grep -E "(error|fail|CMD)"
grep CRON /var/log/syslog | tail -100
Adım 3 – Crontab sözdizimi doğrulama:
crontab -l | grep -v "^#" | grep -v "^$"
Adım 4 – Script testi:
env -i HOME=/home/user LOGNAME=user PATH=/usr/bin:/bin SHELL=/bin/sh
/path/to/script.sh > /tmp/cron_test_output.log 2>&1
cat /tmp/cron_test_output.log
Adım 5 – İzin kontrolü:
ls -la /path/to/script.sh
id $(stat -c '%U' /path/to/script.sh)
Adım 6 – Geçici test cron görevi ekle:
# Her dakika çalışacak test görevi ekle
* * * * * echo "$(date): cron is working" >> /tmp/cron_test.log
# Birkaç dakika bekle ve kontrol et
tail -f /tmp/cron_test.log
Sonuç
Cron sorunlarının %90’ı birkaç temel kategoriye giriyor: PATH sorunları, dosya izinleri, sözdizimi hataları ve log kayıtlarının incelenmemesi. Sistematik bir yaklaşımla, önce servisi kontrol edip, sonra loglara bakıp, ardından script’i cron ortamını simüle ederek test etmek neredeyse her sorunu çözüyor.
En güçlü alışkanlık şu: Yeni bir cron görevi eklerken hemen çıktıyı bir log dosyasına yönlendir. >> /var/log/task.log 2>&1 eklemeyi ihmal etme. Sorun çıktığında saatlerce debug yapmak yerine log dosyasına tek bir bakışla sorunu anlarsın.
Cron sorunları can sıkıcı olabilir ama aynı zamanda çok öğretici. Her sorun giderme süreci, o sistemin nasıl çalıştığını daha iyi anlamamızı sağlıyor. Bir dahaki sefere “cron çalışmıyor” dediğinde artık nereye bakacağını biliyorsun.
