Sunucularda bir şeyler otomatik çalıştırmak söz konusu olduğunda, cron iş birinin aklına gelen ilk araç olur. Ama “crontab -e yap, zamanlama yaz, bitti” diye düşünüyorsan, işlerin bir yerinde ters gideceğini garanti ederim. Kullanıcı crontab’ları, sistem cron dizinleri, anacron, run-parts… Bunların hepsinin ne zaman kullanılacağını bilmek, sabah 3’te alarm kurarak uyandırabilecek türden kazaları önlüyor.
Bu yazıda cron ekosistemini baştan sona ele alacağız. Sadece sözdizimi değil, hangi dosyanın ne zaman kullanılacağı, izin yönetimi, hata ayıklama ve gerçek dünya senaryoları dahil.
Cron Mimarisi: Parçalar ve Görevleri
Linux’ta cron tek bir monolitik yapı değil. Birkaç farklı katmandan oluşuyor:
- crond / cron daemon: Arka planda çalışan ve zamanlamaları takip eden ana servis
- Kullanıcı crontab dosyaları: Her kullanıcıya ait,
crontab -eile yönetilen dosyalar - /etc/crontab: Sistem genelinde geçerli, kullanıcı alanı olan ana cron dosyası
- /etc/cron.d/: Paketlerin ve uygulamaların kendi zamanlamalarını koyduğu dizin
- /etc/cron.hourly/, daily/, weekly/, monthly/: Script’lerin yerleştirileceği hazır dizinler
- /var/spool/cron/: Kullanıcı crontab’larının sistem tarafında depolandığı yer
Pek çok sysadmin /etc/cron.d ile /var/spool/cron farkını karıştırıyor. Şunu net söyleyelim: crontab -e komutunu çalıştırdığında dosyan /var/spool/cron/crontabs/kullaniciadi olarak kaydediliyor. /etc/cron.d ise direkt dosya bırakarak yönetilen, versiyon kontrol sistemine dahil edebileceğin yapılandırma dosyaları için.
Crontab Sözdizimi: Temel ve İleri Düzey
Beş alan ve komut. Klasik format şu şekilde:
# Dakika Saat GünAy Ay HaftaGünü Komut
0 2 * * * /usr/local/bin/backup.sh
Alan açıklamaları:
- Dakika: 0-59
- Saat: 0-23
- Gün (ayın): 1-31
- Ay: 1-12 veya jan, feb…
- Hafta günü: 0-7 (0 ve 7 pazar, 1 pazartesi)
Özel karakterler:
- *: Her değer
- ,: Birden fazla değer (1,15 = 1. ve 15.)
- –: Aralık (1-5 = pazartesiden cumaya)
- /: Her N’de bir (*/5 = her 5 dakikada bir)
Bazı pratik örnekler:
# Her 15 dakikada bir
*/15 * * * * /opt/scripts/healthcheck.sh
# Hafta içi her sabah 8:30'da
30 8 * * 1-5 /usr/bin/python3 /opt/reports/daily_report.py
# Her ayın ilk ve on beşinci günü gece yarısı
0 0 1,15 * * /opt/scripts/billing_sync.sh
# Her Cuma 18:00'de haftalık özet
0 18 * * 5 /opt/scripts/weekly_summary.sh
# Her yıl 1 Ocak saat 00:01'de
1 0 1 1 * /opt/scripts/yearly_archive.sh
Kısa notasyonlar da destekleniyor (Vixie cron ve türevlerinde):
- @reboot: Sistem açılışında bir kez
- @hourly: Her saatin başında (0 )
- @daily: Her gece yarısı (0 0 *)
- @weekly: Her Pazar gece yarısı (0 0 0)
- @monthly: Her ayın birinci günü gece yarısı (0 0 1 )
Kullanıcı Crontab Yönetimi
crontab Komutu ile Çalışmak
# Mevcut kullanıcının crontab'ını düzenle
crontab -e
# Mevcut crontab'ı listele
crontab -l
# Crontab'ı sil (dikkatli! geri yok)
crontab -r
# Başka bir kullanıcının crontab'ını root olarak yönet
crontab -u www-data -e
crontab -u deploy -l
# Bir dosyadan crontab yükle
crontab -u deploy /tmp/deploy-crontab.txt
Kullanıcı crontab’larının sistem tarafındaki dosyalarını direkt düzenleme. /var/spool/cron/crontabs/ altındaki dosyalara elle dokunmak yerine her zaman crontab -e kullan. Aksi halde cron daemon değişikliği fark etmeyebilir ve bazı sistemlerde izin sorunları çıkar.
Editör Seçimi
crontab -e ilk çalıştırıldığında editör seçimi sorar. Bunu kalıcı olarak ayarlamak için:
# Bash için
export EDITOR=nano
echo "export EDITOR=nano" >> ~/.bashrc
# Ya da update-alternatives ile (Debian/Ubuntu)
sudo update-alternatives --config editor
Crontab İzinleri: allow ve deny Dosyaları
Tüm kullanıcıların crontab kullanmasına izin vermek istemeyebilirsin. Kontrol mekanizması şu dosyalarla çalışıyor:
- /etc/cron.allow: Sadece bu dosyadaki kullanıcılar crontab kullanabilir
- /etc/cron.deny: Bu dosyadaki kullanıcılar crontab kullanamaz
Öncelik sırası önemli: cron.allow varsa, deny dosyasına bakılmaz. Sadece allow’dakiler çalıştırabilir. Eğer sadece cron.deny varsa, orada olmayan herkes kullanabilir. İkisi de yoksa genellikle sadece root kullanabilir (dağıtıma göre değişir).
# Sadece belirli kullanıcılara izin ver
echo "deploy" | sudo tee -a /etc/cron.allow
echo "backup_user" | sudo tee -a /etc/cron.allow
# Belirli kullanıcıları engelle
echo "developer1" | sudo tee -a /etc/cron.deny
Sistem Cron Dosyaları
/etc/crontab Yapısı
Kullanıcı crontab’larından farkı, bir kullanıcı alanı içermesi:
# /etc/crontab içeriği örneği
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# Dakika Saat GünAy Ay HaftaGünü Kullanici Komut
17 * * * * root run-parts /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || run-parts /etc/cron.daily
47 6 * * 7 root test -x /usr/sbin/anacron || run-parts /etc/cron.weekly
52 6 1 * * root test -x /usr/sbin/anacron || run-parts /etc/cron.monthly
Dikkat etmen gereken nokta: Bu dosyada her satırda komuttan önce kullanıcı adı yazıyor. Kullanıcı crontab’larında bu alan yok.
/etc/cron.d/ ile Çalışmak
Bu dizin benim en çok tercih ettiğim yapı. Nedeni basit: Her uygulama veya servis kendi cron dosyasını buraya koyuyor, karmaşa olmuyor, versiyon kontrolüne alabiliyorsun.
# Örnek: /etc/cron.d/myapp
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
MAILTO="[email protected]"
# Uygulama veritabanı temizliği - her gece 2:00
0 2 * * * myapp_user /opt/myapp/scripts/cleanup_db.sh >> /var/log/myapp/cleanup.log 2>&1
# Cache temizleme - her saat başı
0 * * * * myapp_user /opt/myapp/scripts/clear_cache.sh
/etc/cron.d dosyaları için kritik kurallar:
- Dosya adında nokta (.) veya tire (-) olmamalı, aksi halde run-parts tarafından görmezden gelinir (bazı sistemlerde)
- Dosya sahibi root olmalı ve sadece root tarafından yazılabilmeli
- Her satırda kullanıcı adı belirtilmeli (/etc/crontab gibi)
# Doğru dosya izinleri
sudo chown root:root /etc/cron.d/myapp
sudo chmod 644 /etc/cron.d/myapp
run-parts ve Cron Dizinleri
/etc/cron.hourly, /etc/cron.daily gibi dizinler aslında çok pratik. Script’ini at, çalışsın. Ama birkaç püf nokta var:
# Script'in çalıştırılabilir olması şart
chmod +x /etc/cron.daily/myscript
# Script dosya adında uzantı OLMAMALI (bazı sistemlerde)
# Yanlış: backup.sh (cron.daily içinde)
# Doğru: backup
# run-parts'ı manuel test et
run-parts --test /etc/cron.daily
run-parts /etc/cron.daily
Ortam Değişkenleri ve PATH Sorunları
Cron job’larının en sık başarısız olma nedeni PATH sorunları. Cron, kullanıcının shell ortamını miras almıyor. Varsayılan PATH genellikle çok kısıtlı: /usr/bin:/bin
# Sorunlu yaklaşım - PATH'de olmayan komut
0 2 * * * python3 backup.py # python3 nerede? cron bilmiyor olabilir
# Doğru yaklaşım 1: Tam yol kullan
0 2 * * * /usr/bin/python3 /opt/scripts/backup.py
# Doğru yaklaşım 2: Crontab'ın başında PATH tanımla
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
0 2 * * * python3 /opt/scripts/backup.py
# Doğru yaklaşım 3: Script içinde ortamı yükle
0 2 * * * /bin/bash -l -c '/opt/scripts/backup.py'
Crontab’da sık kullanılan ortam değişkenleri:
# /var/spool/cron/crontabs/deploy veya /etc/cron.d/myapp
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
[email protected]
HOME=/home/deploy
LANG=tr_TR.UTF-8
MAILTO değişkeni önemli. Boş bırakırsan cron çıktıyı mail atmaz, log’a da yazmaz, sessizce yok olur. Bir adres yazarsan her çıktı oraya mail olarak gider ki bu da production’da rahatsız edici olabilir.
Çıktı Yönetimi ve Loglama
# Tüm çıktıyı log dosyasına yönlendir
0 2 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1
# Tarih damgalı loglama
0 2 * * * echo "[$(date '+%Y-%m-%d %H:%M:%S')] Backup başladı" >> /var/log/backup.log && /opt/scripts/backup.sh >> /var/log/backup.log 2>&1
# Sadece hataları logla, normal çıktıyı görmezden gel
0 2 * * * /opt/scripts/backup.sh > /dev/null 2>> /var/log/backup_errors.log
# logrotate ile büyüyen log dosyalarını yönet
# /etc/logrotate.d/myapp-cron
/var/log/myapp/*.log {
daily
rotate 14
compress
missingok
notifempty
}
Gerçek Dünya Senaryoları
Senaryo 1: Web Uygulaması Backup Sistemi
# /etc/cron.d/webapp-backup
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
[email protected]
# Her gece 1:00'de veritabanı yedeği
0 1 * * * www-data /opt/webapp/scripts/db_backup.sh >> /var/log/webapp/db_backup.log 2>&1
# Her Pazar 2:00'de tam dosya sistemi yedeği
0 2 * * 0 root /opt/webapp/scripts/full_backup.sh >> /var/log/webapp/full_backup.log 2>&1
# 30 günden eski yedekleri temizle - her gün 3:00
0 3 * * * root find /backup/webapp -mtime +30 -name "*.tar.gz" -delete
Senaryo 2: SSL Sertifika Yenileme
Let’s Encrypt sertifikalarının zamanında yenilenmesi kritik. Bunu cron’a bağlamak standart pratik:
# /etc/cron.d/certbot
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# Haftada iki kez yenileme kontrolü (certbot zaten 30 gün dolmadan yenilemiyor)
0 0,12 * * * root python3 -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew --quiet --post-hook "systemctl reload nginx" >> /var/log/certbot-cron.log 2>&1
Buradaki rastgele gecikme Let’s Encrypt’in tavsiye ettiği bir yaklaşım. Milyonlarca sunucunun aynı anda bağlanmasını engelliyor.
Senaryo 3: Deployment Kullanıcısı için Uygulama Görevleri
# deploy kullanıcısının crontab'ı (crontab -u deploy -e)
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin:/home/deploy/.local/bin
MAILTO=""
# Her 5 dakikada bir kuyruk işleyici kontrolü
*/5 * * * * /opt/app/scripts/check_worker.sh
# Her sabah 6:00'da geçici dosyaları temizle
0 6 * * * find /opt/app/tmp -mtime +1 -delete
# Her Pazar 4:00'de istatistik raporu oluştur
0 4 * * 0 /opt/app/scripts/generate_stats.py --weekly >> /opt/app/logs/stats.log 2>&1
Hata Ayıklama Teknikleri
Cron job çalışmıyor mu? Sistematik yaklaşım şart:
# 1. Cron daemon çalışıyor mu?
systemctl status cron # Debian/Ubuntu
systemctl status crond # RHEL/CentOS
# 2. Cron log'larına bak
tail -f /var/log/cron # RHEL/CentOS
tail -f /var/log/syslog # Debian/Ubuntu (cron satırları için grep)
grep CRON /var/log/syslog | tail -20
# 3. Komutu manuel olarak cron ortamında test et
# Cron'un ortamını simüle et
env -i HOME=/root SHELL=/bin/bash PATH=/usr/bin:/bin /komutun/tam/yolu
# 4. Script izinlerini kontrol et
ls -la /opt/scripts/backup.sh
# Çalıştırılabilir olmalı ve doğru sahibi olmalı
# 5. Crontab sözdizimini doğrula
# Online araç: crontab.guru
# Ya da şunu dene:
crontab -l | grep -v "^#"
Çok sık karşılaşılan sorunlar:
- Script çalıştırılabilir değil:
chmod +xunutulmuş - PATH sorunu: Komut tam yol olmadan yazılmış
- Ortam değişkeni eksik: Script shell’den farklı davranıyor
- Dosya izni: Script root izni gerektiriyor ama kullanıcı crontab’ında çalışıyor
- Satır sonu sorunu: Windows’tan kopyalanan script’lerde
rnsorunu
# Windows satır sonlarını düzelt
sed -i 's/r//' /opt/scripts/backup.sh
# Ya da
dos2unix /opt/scripts/backup.sh
Crontab’ı Versiyon Kontrolünde Tutmak
Production ortamında crontab’ları versiyon kontrolüne almak çok önemli. /etc/cron.d/ zaten bu için biçilmiş kaftan:
# Git reposunda cron dosyalarını tut
# /srv/config/cron.d/webapp-tasks olarak sakla
# Deploy sırasında kopyala
# Ansible ile yönetim
# cron modülü ile
- name: Backup cron job
ansible.builtin.cron:
name: "nightly database backup"
minute: "0"
hour: "1"
user: www-data
job: "/opt/webapp/scripts/db_backup.sh >> /var/log/webapp/db_backup.log 2>&1"
# Ya da template ile /etc/cron.d dosyası deploy et
- name: Deploy webapp cron file
ansible.builtin.template:
src: templates/webapp-cron.j2
dest: /etc/cron.d/webapp
owner: root
group: root
mode: '0644'
Systemd Timer ile Karşılaştırma
Modern sistemlerde cron’a alternatif olarak systemd timer kullanılabiliyor. Her ikisini de bilmek gerekiyor:
Cron’un avantajları:
- Basit sözdizimi, hızlı kurulum
- Her Linux dağıtımında var
- Kullanıcı bazlı yönetim kolay
Systemd timer avantajları:
- Bağımlılık yönetimi (servis A çalışmadan başlama)
- Daha iyi loglama (journalctl ile)
- Monotonic timer (sistem kapalıyken atlanmış görevleri telafi etme)
- Resource limiting (cgroups ile)
Ancak basit periyodik görevler için cron hala en pragmatik çözüm. 2025’te de cron bilmek şart.
Güvenlik Notları
# Crontab dosyalarının izinlerini kontrol et
ls -la /var/spool/cron/crontabs/
# Her dosya sadece sahibi tarafından okunabilmeli
# /etc/cron.d altındaki dosyalar
ls -la /etc/cron.d/
# Hepsi root sahibi olmalı, 644 veya daha kısıtlayıcı
# Dünyaya açık (world-writable) cron script'leri tehlikeli
find /etc/cron* /var/spool/cron -perm -o+w 2>/dev/null
# Bu komut bir şey döndürürse sorun var demektir
# Sudoers'a gerek kalmadan root yetkisi gereken işleri
# root'un kendi crontab'ına veya /etc/cron.d'ye koy
# www-data'ya sudo vermek yerine
Sonuç
Cron yönetimi sysadmin’liğin temel becerilerinden biri. Ama “sadece crontab -e yap” demek, buzdağının görünen yüzünü anlatmak olur. Kullanıcı crontab’ları, /etc/cron.d, sistem crontab’ı… Hepsinin farklı kullanım senaryosu var.
Pratikte en sağlıklı yaklaşım: Uygulama bazlı işler için /etc/cron.d altında ayrı dosyalar oluştur, bu dosyaları versiyon kontrolüne al, her cron job’ının çıktısını düzgünce logla. Bir job çalışmıyorsa /var/log/syslog veya /var/log/cron’a bak, komutun tam yolu ile PATH sorununu dışla, sonra izinlere bak.
Cron basit görünür, ama production’da saat 2’de neden backup almadığını araştırırken anlaşılır neden bu kadar detay önemli. Bu yüzden crontab’larını yazdığında her zaman şunu sor: “Bu, cron’un ortamında da çalışır mı?”