Cron Log Analizi: Zamanlı Görev Hatalarını Bulma ve Çözme

Sabah işe geldiğinizde yedekleme scriptinizin çalışmadığını, veritabanı temizleme görevinizin hata verdiğini ya da raporlama cronunuzun sessiz sedasız başarısız olduğunu fark etmek oldukça sinir bozucu bir durum. Cron joblar, sistem yöneticilerinin en güvendiği araçların başında gelir ama aynı zamanda en sık “sessiz acı çeken” bileşenlerden de biridir. Bu yazıda, cron loglarını sistematik biçimde analiz ederek sorunları hızlıca nasıl tespit edeceğinizi, hangi araçları kullanmanız gerektiğini ve gerçek dünya senaryolarında nasıl yaklaşım sergilemeniz gerektiğini ele alacağız.

Cron Logları Nerede Bulunur?

Sisteminize göre cron loglarının konumu değişebilir. Bu noktada dağıtımlar arasındaki farkları bilmek, hayat kurtarır.

Debian/Ubuntu tabanlı sistemlerde:

/var/log/syslog
# veya
/var/log/cron.log

RHEL/CentOS/Rocky Linux tabanlı sistemlerde:

/var/log/cron

Systemd tabanlı modern sistemlerde (journald ile):

journalctl -u cron
# veya
journalctl -u crond

Eğer /var/log/cron.log dosyası Debian/Ubuntu sistemlerde yoksa, rsyslog yapılandırmasında cron loglaması devre dışı bırakılmış olabilir. Aktifleştirmek için şunu yapın:

sudo nano /etc/rsyslog.d/50-default.conf
# cron.* /var/log/cron.log satırını uncomment edin
sudo systemctl restart rsyslog

Bu temel bilgiyle başladıktan sonra asıl analize geçelim.

Temel Log Okuma Teknikleri

Ham cron logu başlangıçta karmaşık görünebilir. Tipik bir satır şu şekilde görünür:

Jan 15 03:00:01 webserver01 CRON[12453]: (root) CMD (/usr/local/bin/backup.sh)
Jan 15 03:00:01 webserver01 CRON[12453]: (CRON) info (No MTA installed, discarding output)

İlk satırda tarih, saat, sunucu adı, süreç ID’si, çalıştıran kullanıcı ve komut görünüyor. İkinci satır ise çıktının gönderilemediğini söylüyor, ki bu başlı başına bir sorun işareti.

Belirli bir kullanıcının cron joblarını filtrelemek için:

grep "CRON" /var/log/syslog | grep "(deploy)" | tail -50

Sadece hata içeren satırları bulmak için:

grep -i "error|fail|warning|ERR" /var/log/syslog | grep "CRON"

Belirli bir tarih aralığında cron aktivitesine bakmak:

awk '/Jan 15 02:00/,/Jan 15 04:00/' /var/log/syslog | grep "CRON"

Bu üç komut, günlük analizin temel taşları. Ama daha derine inmek gerektiğinde farklı yöntemlere ihtiyaç duyarsınız.

Sessiz Başarısızlıkları Tespit Etmek

Cron dünyasındaki en tehlikeli sorun, sessiz başarısızlıklardır. Script çalışıyor gibi görünür, log dosyasına “CMD” satırı düşer, ancak script içinde bir şeyler yanlış gider ve kimse haberdar olmaz. Bunu tespit etmek için birkaç yöntem var.

Exit Code’ları Yakalamak

Cron joblarınızı şu şekilde düzenleyerek exit code kontrolü ekleyebilirsiniz:

# /etc/cron.d/backup-job dosyası
0 3 * * * root /usr/local/bin/backup.sh >> /var/log/backup-cron.log 2>&1; echo "Exit: $?" >> /var/log/backup-cron.log

Bu yaklaşım, scriptin başarılı bitip bitmediğini doğrudan loga yazdırır. Sabah grep "Exit:" /var/log/backup-cron.log | grep -v "Exit: 0" çalıştırdığınızda sıfır dışı exit code’ları hemen görürsünüz.

Zamanlama Tutarsızlıklarını Bulmak

Bir cron job her gün belirli bir saatte çalışması gerekirken arada kayıp günler varsa, bunu şu şekilde tespit edebilirsiniz:

grep "backup.sh" /var/log/syslog | awk '{print $1, $2}' | sort | uniq -c

Bu komut, hangi gün kaç kez çalıştığını gösterir. Beklediğinizden az sayı görüyorsanız, bir sorun var demektir.

Gerçek dünya senaryosu: Bir e-ticaret şirketinde gece 02:00’de çalışan envanter senkronizasyon scripti, ayda ortalama 2-3 kez sessizce başarısız oluyordu. Kimse fark etmemişti çünkü script logda “CMD” olarak görünüyordu. Aşağıdaki analiz ile bu ortaya çıktı:

# Son 30 günlük envanter sync çalışmalarını sayalım
grep "inventory_sync.sh" /var/log/syslog | 
  awk '{print $1" "$2}' | 
  sort -k1,1M -k2,2n | 
  uniq -c | 
  awk '$1 != 1 {print "ANORMAL: "$0} $1 == 1 {print "NORMAL: "$0}'

Bazı günlerde script birden fazla başlatılmış, bazı günlerde hiç çalışmamıştı. Bu, sunucunun zaman zaman yeniden başlatıldığının ve cron servisinin tam olarak başlamadan önce zamanlama penceresinin geçtiğinin işaretiydi.

Journald ile Gelişmiş Cron Analizi

Modern sistemlerde journalctl kullanmak, klasik log dosyası okumaktan çok daha güçlü. Özellikle filtreleme seçenekleri açısından ciddi avantaj sağlar.

# Son 24 saatteki cron aktivitesi
journalctl -u cron --since "24 hours ago" --no-pager

# Belirli bir zaman aralığı
journalctl -u cron --since "2024-01-15 02:00:00" --until "2024-01-15 04:00:00"

# Sadece hata seviyesindeki mesajlar
journalctl -u cron -p err --since today

# JSON formatında çıktı (başka araçlarla işlemek için)
journalctl -u cron --since "1 hour ago" -o json | python3 -m json.tool | grep -A5 "MESSAGE"

Journald’ın en güçlü özelliklerinden biri, belirli bir süreç ID’sine göre filtreleyebilmek. Bir cron job’un tam çıktısını görmek istediğinizde şunu kullanın:

# Önce PID'yi bulun
journalctl -u cron --since today | grep "backup.sh" | head -5
# Çıktıdan CRON[12453] gibi bir PID alacaksınız

# Sonra o PID'nin tüm loglarını görün
journalctl _PID=12453

Özel Cron Log Analiz Scripti

Günlük rutin analiz için kullanabileceğiniz kapsamlı bir bash scripti yazalım. Bu script, her sabah çalıştırılıp size bir özet rapor verebilir:

#!/bin/bash
# cron_analyzer.sh - Günlük cron log analiz scripti

LOG_FILE="/var/log/syslog"
REPORT_DATE=$(date -d "yesterday" "+%b %e")
OUTPUT_FILE="/tmp/cron_report_$(date +%Y%m%d).txt"

echo "===== CRON ANALIZ RAPORU: $REPORT_DATE =====" > "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"

# Toplam cron job sayısı
TOTAL_JOBS=$(grep "$REPORT_DATE" "$LOG_FILE" | grep "CRON" | grep "CMD" | wc -l)
echo "Toplam cron calismasi: $TOTAL_JOBS" >> "$OUTPUT_FILE"

# Kullaniciya gore dagilim
echo "" >> "$OUTPUT_FILE"
echo "--- Kullaniciya Gore Dagilim ---" >> "$OUTPUT_FILE"
grep "$REPORT_DATE" "$LOG_FILE" | grep "CRON" | grep "CMD" | 
  grep -oP '(K[^)]+(?=) CMD)' | sort | uniq -c | sort -rn >> "$OUTPUT_FILE"

# Hata ve uyarı satirlari
echo "" >> "$OUTPUT_FILE"
echo "--- Hatalar ve Uyarilar ---" >> "$OUTPUT_FILE"
ERRORS=$(grep "$REPORT_DATE" "$LOG_FILE" | grep "CRON" | grep -i "error|fail|no MTA")
if [ -z "$ERRORS" ]; then
    echo "Hata bulunamadi." >> "$OUTPUT_FILE"
else
    echo "$ERRORS" >> "$OUTPUT_FILE"
fi

# MTA uyarilari (mail gonderilemeyen cron outputlari)
echo "" >> "$OUTPUT_FILE"
echo "--- Mail Gonderilemeyen Cron Outputlari ---" >> "$OUTPUT_FILE"
MTA_COUNT=$(grep "$REPORT_DATE" "$LOG_FILE" | grep "No MTA installed" | wc -l)
echo "Toplam $MTA_COUNT cron output maili gonderilemedi" >> "$OUTPUT_FILE"

cat "$OUTPUT_FILE"
echo ""
echo "Rapor $OUTPUT_FILE dosyasina kaydedildi."

Bu scripti crontab’a ekleyerek her sabah mail ile kendinize göndertebilirsiniz:

0 8 * * * root /usr/local/bin/cron_analyzer.sh | mail -s "Gunluk Cron Raporu" [email protected]

Logrotate ile Cron Log Yönetimi

Cron logları zaman içinde şişer. Özellikle yoğun sunucularda günlük yüzlerce megabayt log üretilebilir. Logrotate yapılandırması burada kritik önem taşır.

# /etc/logrotate.d/cron-custom dosyası
/var/log/cron.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 640 root adm
    postrotate
        /usr/bin/systemctl reload rsyslog > /dev/null 2>&1 || true
    endscript
}

Rotate sonrası logları arşivden analiz etmek için:

# Gzipli log dosyasında arama
zgrep "backup.sh" /var/log/syslog.2.gz

# Birden fazla arşivde arama
for f in /var/log/syslog*.gz; do
    echo "=== $f ==="
    zgrep "CRON.*error" "$f" 2>/dev/null
done

Gerçek Senaryo: Yedekleme Cron’unun Analizi

Diyelim ki production veritabanı yedeğini alan bir cron job’unuz var ve son backup’ın ne zaman başarılı olduğunu bilmiyorsunuz. İşte adım adım analiz süreci:

# 1. Adım: Job'un son ne zaman çalıştığını bulun
grep "db_backup.sh" /var/log/syslog | tail -20

# 2. Adım: Son çalışmaların PID'lerini çıkarın
grep "db_backup.sh" /var/log/syslog | grep "CMD" | 
  awk '{match($0, /CRON[([0-9]+)]/, arr); print arr[1], $1, $2, $3}' | tail -10

# 3. Adım: Belirli bir PID için tüm logları inceleyin
# (12876 örnek PID)
grep "[12876]" /var/log/syslog

# 4. Adım: Script kendi log dosyasına yazıyorsa oraya bakın
tail -100 /var/log/db_backup.log | grep -E "ERROR|SUCCESS|WARN|start|finish"

# 5. Adım: Son başarılı yedeğin boyutunu kontrol edin
ls -lah /backup/db/ | tail -10

Bu adımlar sonunda genellikle şu senaryolardan biriyle karşılaşırsınız: disk dolmuş ve script yazamıyor, veritabanı şifresi değişmiş ama script güncellenmemiş, ya da hedef dizin izinleri bozulmuş.

Disk dolması senaryosunun log çıktısı şuna benzer:

Jan 15 03:00:01 dbserver CRON[9923]: (root) CMD (/usr/local/bin/db_backup.sh)
Jan 15 03:00:45 dbserver CRON[9923]: (root) INFO (db_backup.sh: No space left on device)

Bu mesajı görür görmez df -h ve du -sh /backup/* komutlarıyla disk durumuna bakın.

Cron Zamanlama Hatalarını Tespit Etmek

Bazen script çalışıyor ama yanlış zamanda çalışıyor. Bu da ciddi bir sorun olabilir. Özellikle timezone karmaşası büyük bir tuzaktır.

Sistemin timezone’unu ve cron’un hangi timezone’u kullandığını kontrol edin:

# Sistem timezone
timedatectl status | grep "Time zone"

# Cron servisi environment'ı
systemctl show cron | grep -i timezone

# Root crontab'daki CRON_TZ değişkeni
crontab -l | grep CRON_TZ

# Bir cron job'un tam olarak hangi saatte çalıştığını logdan doğrulayın
grep "weekly_report.sh" /var/log/syslog | awk '{print $1, $2, $3}' | sort | uniq

Eğer bir sunucu UTC’de çalışıyorsa ve siz yerel saat ile cron yazdıysanız, job yanlış saatte çalışıyor demektir. Bu durumu düzeltmek için:

# Crontab'a timezone ekleyin
CRON_TZ=Europe/Istanbul
0 3 * * * /usr/local/bin/backup.sh

Log Analizi İçin Faydalı Araçlar

Elle komut yazmak yerine bazı araçlar bu işi kolaylaştırır.

GoAccess ile cron log görselleştirmesi: GoAccess normalde web log analizi için kullanılsa da özel format tanımıyla cron loglarını da işleyebilir. Ancak en pratik araçlar yine bash tabanlı olanlar.

AWK ile güçlü analiz:

# Saat bazında cron job yoğunluğunu göster
grep "CMD" /var/log/syslog | awk '{
    split($3, t, ":")
    hours[t[1]]++
}
END {
    for (h in hours) print h":00 -", hours[h], "job"
}' | sort

# En çok çalışan 10 cron job
grep "CMD" /var/log/syslog | grep -oP 'CMD (K[^)]+' | 
  sort | uniq -c | sort -rn | head -10

# Ortalama cron job süresi (başlangıç ve bitiş logları varsa)
grep "backup.sh" /var/log/syslog | awk '
/CMD/ {start[$5] = mktime(sprintf("%s %d %s", $2, $3, $1))}
/END/ {if ($5 in start) print $5, ":", mktime(sprintf(...)) - start[$5], "saniye"}
'

Alerting: Cron Hatalarında Anlık Bildirim

Logları analiz etmek reaktif bir yaklaşım. Proaktif olmak için cron hatalarında anında bildirim alın.

#!/bin/bash
# /usr/local/bin/cron_watcher.sh
# Bu scripti systemd timer veya başka bir cron ile 5 dakikada bir çalıştırın

SLACK_WEBHOOK="https://hooks.slack.com/services/XXXX/YYYY/ZZZZ"
CHECK_INTERVAL=5  # dakika

# Son 5 dakikadaki cron hatalarını bul
ERRORS=$(journalctl -u cron --since "$CHECK_INTERVAL minutes ago" | 
  grep -iE "error|fail|permission denied|command not found" | 
  grep -v "^--")

if [ -n "$ERRORS" ]; then
    MESSAGE="*CRON HATASI TESPIT EDILDI* - $(hostname)n```n$ERRORSn```"
    curl -s -X POST -H 'Content-type: application/json' 
      --data "{"text":"$MESSAGE"}" 
      "$SLACK_WEBHOOK"
fi

Bu scripti 5 dakikada bir çalışacak şekilde crontab’a ekleyin:

*/5 * * * * root /usr/local/bin/cron_watcher.sh

Not: Watcher scriptinin kendi hata durumunda sonsuz döngüye girmemesi için dikkatli olun. Script içinde cron_watcher.sh’ın kendi loglarını grep’lemeyin.

Cron ile İlgili Yaygın Hata Mesajları ve Anlamları

Logda sık karşılaşılan mesajları ve ne anlama geldiklerini bilmek, analizi hızlandırır.

  • (CRON) info (No MTA installed, discarding output): Script çıktı üretiyor ama mail göndermek için MTA (sendmail, postfix gibi) kurulu değil. Çıktıyı bir log dosyasına yönlendirin.
  • (root) MAIL (mailed 47 bytes of output from 1 job): Cron job çıktı üretti ve bunu root’a maillemeye çalıştı.
  • CRON (username): bad minute errors in crontab file, can’t install: Crontab syntax hatası var. crontab -l ile kontrol edin.
  • (username) CMD (komut): Permission denied: Script çalıştırma izni yok ya da sudo yetkisi eksik.
  • execve: No such file or directory: Script dosyası silinmiş, taşınmış ya da shebang satırı yanlış.
  • (CRON) error (grandchild #12453 failed with exit status 1): Alt süreç hata kodu döndürdü.
  • Authentication failure: PAM kimlik doğrulama hatası, genellikle izin sorunlarından kaynaklanır.

Log Analizi Otomasyonu: Günlük Rapor Sistemi

Son olarak, her şeyi bir araya getiren kapsamlı bir log analiz sistemi kuralım. Bu yapı, birden fazla sunucudan cron log özetlerini toplayıp merkezi bir noktada raporlar.

#!/bin/bash
# /usr/local/bin/daily_cron_report.sh

HOSTNAME=$(hostname)
DATE=$(date "+%Y-%m-%d")
YESTERDAY=$(date -d yesterday "+%b %e")
REPORT=""

# Sistem bilgisi
REPORT+="Sunucu: $HOSTNAME | Tarih: $DATEn"
REPORT+="========================================nn"

# Dun kac cron job calisti
TOTAL=$(grep "$YESTERDAY" /var/log/syslog | grep "CRON.*CMD" | wc -l)
REPORT+="Toplam cron calismasi: $TOTALn"

# Basarisiz goruntuler
FAILS=$(grep "$YESTERDAY" /var/log/syslog | grep "CRON" | 
  grep -c "error|fail|status [^0]|No such file")
REPORT+="Potansiyel hata sayisi: $FAILSnn"

# En cok calisan 5 job
REPORT+="En Cok Calisan Joblar:n"
TOP_JOBS=$(grep "$YESTERDAY" /var/log/syslog | grep "CRON.*CMD" | 
  grep -oP 'CMD (K[^)]+' | sort | uniq -c | sort -rn | head -5)
REPORT+="$TOP_JOBSnn"

# Hata detaylari
if [ "$FAILS" -gt 0 ]; then
    REPORT+="Hata Detaylari:n"
    ERROR_DETAIL=$(grep "$YESTERDAY" /var/log/syslog | grep "CRON" | 
      grep "error|fail|No such file" | tail -20)
    REPORT+="$ERROR_DETAILn"
fi

echo -e "$REPORT"

# Eger hata varsa mail at
if [ "$FAILS" -gt 0 ]; then
    echo -e "$REPORT" | mail -s "[$HOSTNAME] Cron Hata Raporu - $DATE" [email protected]
fi

Bu script, sistematik cron log yönetiminin temel taşı haline gelir. Her sabah otomatik çalışır, hata yoksa sessiz kalır, hata varsa sizi uyarır.

Sonuç

Cron log analizi, reaktif bir “bir şeyler bozuldu, bakalım” yaklaşımından proaktif bir “sistemi sürekli izliyorum” yaklaşımına geçiş gerektiriyor. Bu yazıda ele aldığımız teknikler, hem anlık sorun tespiti hem de uzun vadeli sistem sağlığı izlemesi için kullanılabilir.

En kritik alışkanlıklar şunlar: Tüm cron job çıktılarını mutlaka bir log dosyasına yönlendirin, exit code’larını kaydedin, sessiz başarısızlıklara karşı aktif kontroller kurun ve zamanlama tutarsızlıklarını düzenli olarak kontrol edin. “No MTA installed” mesajı görüyorsanız bu, cron çıktılarınızın kaybolduğunun işaretidir, bunu düzeltmeyi erttelemeyin.

Bir sysadmin olarak şunu söyleyebilirim: En kötü cron hatası, var olduğundan haberiniz olmayan hatadır. Loglama altyapısını sağlam kurun, otomatik rapor sistemleri oluşturun ve özellikle kritik işlemleri (yedekleme, faturalandırma, raporlama) ikili kontrol mekanizmalarıyla donatın. Gece 03:00’de çalışan bir script, siz uyurken başarısız olabilir. Sabah sizi bilgilendiren bir sistem olmadan bu başarısızlık günlerce fark edilmeyebilir.

Benzer Konular

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir