Crontab'a satır eklediniz, saat geldi ama dosya oluşmadı, yedek alınmadı veya e-posta gitmedi. Cron job çoğu zaman sessizce başarısız olur: ekranda uyarı yoktur, yalnızca log veya yönlendirdiğiniz dosya gerçeği söyler. Bu rehber, "hiç tetiklenmedi" ile "tetiklendi ama komut çöktü" ayrımını netleştirir; Linux sunucularda (Debian/Ubuntu, CentOS/RHEL) adım adım teşhis ve düzeltme sunar.
Terminalde çalışan bir komutun cron'da bozulması neredeyse her zaman ortam farkından kaynaklanır: kısıtlı PATH, yüklenmeyen .bashrc, /bin/sh kabuğu, home çalışma dizini ve kaçırılmamış % karakteri. Crontab sözdizimi hataları da görevin hiç başlamamasına yol açar. İzin kaynaklı Permission denied için ayrıca permission denied rehberine bakın.
Aşağıdaki sıra bilinçlidir: önce cron'un komutu başlatıp başlatmadığını kanıtlayın, sonra ortamı ve script'i düzeltin. Rastgele chmod 777 veya "her şeyi root'a taşıma" hem güvenlik riski yaratır hem de asıl hatayı gizler.
Sistematik Teşhis: Önce Log, Sonra Ortam
İki farklı sorun vardır. Komut başlatma kayıtları etkin olduğu halde logda CMD yoksa servis, yanlış kullanıcı crontab'ı veya sözdizimi sorunu olabilir; önce doğru log kaynağını incelediğinizi doğrulayın. CMD varsa cron tetiklemiştir; hata script veya ortam tarafındadır. Çıktıyı görmek için satırın sonuna yönlendirme ekleyin.
- Servisi kontrol edin:
systemctl status cron(Debian/Ubuntu) veyasystemctl status crond(CentOS/RHEL). - Doğru crontab'ı listeleyin:
crontab -l; root içinsudo crontab -l; sistem satırları için/etc/crontabve/etc/cron.d/. - Logda CMD arayın (ayrıntılar için cron job log rehberi).
- Komutu aynı kullanıcıyla manuel çalıştırın.
- Cron benzeri boş ortamda deneyin:
env -i HOME="$HOME" PATH="/usr/bin:/bin" /bin/sh -c '/tam/yol/script.sh'. - Çıktıyı dosyaya alın:
>> /var/log/gorev.log 2>&1.
# Debian / Ubuntu
sudo grep CRON /var/log/syslog | tail -30
sudo journalctl -u cron --since "2 hours ago"
# CentOS / RHEL / Rocky
sudo tail -30 /var/log/cron
sudo journalctl -u crond --since "2 hours ago"
Tipik bir başarılı kayıt şöyle görünür: CRON[12345]: (deploy) CMD (/usr/bin/php /var/www/site/artisan schedule:run). Bu satır exit kodunu göstermez; script çıktısı için kendi logunuz şarttır.
Listeleme sırasında hangi kullanıcının tablosunu gördüğünüzü doğrulamak için crontab -l çıktısını kullanıcı bazında yorumlama adımlarını izleyin; root'un tablosunda aradığınız satır uygulama kullanıcısında olabilir. Uygulamanın genel erişilebilirliğini ayrıca ölçmek istiyorsanız cron görevleriyle uptime izlemenin birlikte kullanımı, zamanlayıcı hatasıyla site kesintisini ayırmanıza yardım eder.
Komut başlamış ama beklenen sonucu üretmemişse yalnızca servis loguna güvenmeyin. Görevin son başarılı adımdan sonra dış bir ölçüm noktasına sinyal gönderdiği heartbeat ile sessiz cron hatalarını yakalama yaklaşımı, sinyalin gelmemesini ayrı bir alarm koşulu olarak değerlendirir; başlangıç CMD kaydı bu sinyalin yerine geçmez.
Cron Servisi ve Crontab Kontrolleri
Servis kapalıysa hiçbir kullanıcı görevi çalışmaz. Dağıtıma göre birim adı cron veya crond olur.
systemctl status cron
sudo systemctl start cron
sudo systemctl enable cron
# RHEL ailesi
systemctl status crond
sudo systemctl start crond && sudo systemctl enable crond
/etc/cron.allow varsa yalnızca listedeki kullanıcılar crontab kullanabilir; adınız yoksa satır ekleseniz bile kabul edilmeyebilir. cron.deny ile birlikte kullanımda allow önceliklidir. Sistem görevleri çoğu zaman /etc/crontab veya /etc/cron.d/ altındadır ve kullanıcı alanı altıncı alandadır — kişisel crontab ile karıştırmayın.
cat /etc/cron.allow 2>/dev/null
cat /etc/cron.deny 2>/dev/null
ls -la /etc/cron.d/
crontab -l
crontab -e ile kaydedip en sonda boş satır bırakın.PATH, Shell ve Ortam Değişkenleri
Cron'un varsayılan PATH değeri çoğu sistemde /usr/bin:/bin (veya benzeri kısa bir listedir). python3, node, composer veya /usr/local/bin altındaki araçlar terminalde bulunur, cron'da not found verir (exit 127).
# YANLIŞ — PATH'te olmayabilir
*/5 * * * * php /var/www/site/cron.php
# DOĞRU — mutlak yol
*/5 * * * * /usr/bin/php /var/www/site/cron.php
# veya crontab başında
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
SHELL=/bin/bash
*/5 * * * * php /var/www/site/cron.php
Cron varsayılan kabuğu /bin/sh'dir; Bash dizileri, [[ ]] ve bazı yönlendirmeler çalışmayabilir. Script'te #!/bin/bash kullanın veya crontab'da SHELL=/bin/bash tanımlayın. JAVA_HOME, NODE_ENV, sanal ortam (venv) ve nvm yolları yüklenmez; bunları crontab satırında veya script içinde export / source ile verin.
* * * * * env > /tmp/cron-env.txt 2>&1
# Script içinde
#!/bin/bash
set -euo pipefail
cd /home/deploy/proje || exit 1
set -a
source /home/deploy/proje/.env
set +a
/home/deploy/proje/venv/bin/python /home/deploy/proje/jobs/cleanup.py
Çalışma dizini kullanıcının home dizinidir. ./scripts/gorev.sh veya göreli config yolları yanlış yere bakar. Her zaman mutlak yol veya satır başında cd /hedef && kullanın.
İzinler, Sözdizimi ve Özel Karakterler
Script çalıştırılamıyorsa log veya yönlendirme dosyasında Permission denied (exit 126) görürsünüz. chmod +x, doğru sahip ve üst dizinlerde geçiş (x) izni gerekir.
ls -la /home/deploy/scripts/yedek.sh
chmod 755 /home/deploy/scripts/yedek.sh
# Gerekirse: chown deploy:deploy /home/deploy/scripts/yedek.sh
Beş alanın ilki dakikadır: 0 3 * * * saat 03:00, 3 0 * * * ise 00:03 demektir. İfadeyi cron ifade üreticisi ile doğrulayın.
Crontab'da % özeldir: kaçırılmazsa komutu böler ve geri kalanı stdin olur. date +%Y%m%d sessizce bozulur.
# YANLIŞ
0 3 * * * echo $(date +%Y%m%d) > /tmp/tarih.txt
# DOĞRU
0 3 * * * echo $(date +\%Y\%m\%d) > /tmp/tarih.txt
Çıktı yönlendirmesi yoksa cron çıktıyı e-posta ile göndermeye çalışır; MTA yoksa veya MAILTO boşsa hata kaybolur. Her zaman >> /var/log/... 2>&1 ekleyin. Uzun görevler üst üste binebilir; flock -n ile kilitleyin.
0 3 * * * /home/deploy/scripts/yedek.sh >> /var/log/yedek.log 2>&1
*/5 * * * * /usr/bin/flock -n /run/yedek.lock /home/deploy/scripts/uzun.sh >> /var/log/uzun.log 2>&1
Gerçek Senaryolar
Senaryo 1: Gece 02:00 veritabanı yedeği alınmıyor
Operasyon ekibi sabah yedek klasörünün boş kaldığını fark eder. journalctl -u cron içinde 02:00'de CMD vardır; özel logda ise /bin/sh: 1: mysqldump: not found yazar. Sebep: mysqldump PATH'te yok. Çözüm: /usr/bin/mysqldump ve kimlik bilgilerini ~/.my.cnf (izin 600) üzerinden vermek; şifreyi crontab satırına yazmamak.
Senaryo 2: Laravel schedule her dakika "çalışıyor" ama iş yapmıyor
Logda her dakika php artisan schedule:run CMD görünür. Manuel çalışınca işler tetiklenir; cron'da sessiz kalır. Sebep: cron satırında proje dizinine cd yoksa göreli artisan yolu bulunamayabilir. Çözüm: * * * * * cd /var/www/site && /usr/bin/php artisan schedule:run >> /var/log/laravel-schedule.log 2>&1. Ayrıntılı kurulum için Laravel cron job rehberine bakın.
Sık Hatalar ve Çözümleri
| Belirti / hata mesajı | Neden | Çözüm |
|---|---|---|
| Logda hiç CMD yok | Servis kapalı, yanlış crontab, sözdizimi veya log yapılandırması | systemctl status, crontab -l, log yapılandırması |
/bin/sh: 1: php: not found | Kısıtlı PATH | Mutlak yol veya crontab PATH= |
Permission denied | Execute bit veya dizin traverse eksik | chmod +x, sahiplik; bkz. permission denied rehberi |
date çıktısı boş / garip | Kaçırılmamış % | \% veya script dosyası |
| Komut terminalde OK, cron'da fail | Ortam / cwd / shell farkı | env -i testi, cd, SHELL=/bin/bash |
| Disk full / yazılamıyor | df -h dolu veya log izni | Alan açın; log dizinine yazma izni |
| SELinux AVC / AppArmor deny | MAC politikası | ausearch / aa-status; politika düzeltin (kalıcı setenforce 0 önermeyiz) |
| İkinci kopya çakışması | Önceki çalışma bitmeden yeni tetik | flock -n |
# Script'i debug modda manuel test
bash -x /home/deploy/scripts/yedek.sh
/home/deploy/scripts/yedek.sh; echo "exit=$?"
# Disk
df -h
# SELinux (RHEL)
sudo ausearch -m avc -c crond | tail
cronjob.com.tr ile HTTP Tabanlı Alternatif
Görev bir URL ile tetiklenebiliyorsa (ör. PHP/Laravel endpoint, WordPress bakım URL'si) sunucuda crontab, PATH ve izin savaşını bırakıp dışarıdan HTTP çağrısı kullanabilirsiniz. Uç noktayı gizli bir header ile koruyun:
<?php
// /var/www/site/public/cron-run.php
declare(strict_types=1);
$beklenen = getenv('CRON_SECRET') ?: '';
$token = $_SERVER['HTTP_X_CRON_TOKEN'] ?? '';
if ($beklenen === '' || !hash_equals($beklenen, $token)) {
http_response_code(403);
echo 'forbidden';
exit;
}
// İş mantığı: yedek, kuyruk, temizlik...
http_response_code(200);
echo 'ok';
cronjob.com.tr panelinde bu URL'yi ekleyin: metot GET veya POST, header X-Cron-Token: ..., zamanlama 1 dakikadan başlayan hazır aralık veya 5 alanlı cron ifadesi, saat dilimi (varsayılan Europe/Istanbul). Servis ücretsizdir; kayıtta kredi kartı istenmez. Başarı HTTP 200–399 ve bağlantı hatası olmamasıdır. Yanıt bekleme süresi aralığa göre ayarlanır (1 dk → 55 sn, 2 dk → 115 sn, 5 dk ve üzeri veya cron ifadeli işler → en fazla 290 sn). Ardışık hata eşiği (varsayılan 3) aşılınca e-posta gider; düzelince kesinti süresiyle bildirim gelir. Her çalışmanın durum kodu, süresi, hata metni ve yanıt gövdesinin ilk ~64 KB'ı 7 gün saklanır. Yerel ağ / localhost adreslerine istek gönderilmez; HTTPS sertifikası doğrulanır.
Sıkça Sorulan Sorular (SSS)
Cron job neden çalışmıyor?
En sık nedenler: cron servisinin kapalı olması, yanlış crontab kullanıcısı, kısıtlı PATH, çalıştırma izni eksikliği, kaçırılmamış yüzde (%) karakteri ve çıktının görünmeden kaybolmasıdır. Önce logda CMD satırını arayın.
Cron job çalışıp çalışmadığını nasıl anlarım?
Ubuntu/Debian'da grep CRON /var/log/syslog veya journalctl -u cron; CentOS/RHEL'de /var/log/cron veya journalctl -u crond kullanın. CMD satırı varsa cron komutu başlatmıştır; yoksa log yapılandırmasını, zamanlamayı ve servisi kontrol edin.
Cron job PATH hatası nasıl çözülür?
Cron ortamında PATH genelde /usr/bin:/bin ile sınırlıdır. Komutlarda tam yol kullanın (/usr/bin/python3) veya crontab başına PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ekleyin.
Terminalde çalışan komut cron'da neden başarısız olur?
Cron ~/.bashrc yüklemez; SHELL çoğu sistemde /bin/sh'dir, çalışma dizini home'dur ve ortam değişkenleri eksiktir. Mutlak yollar, crontab içinde PATH/SHELL ve çıktı yönlendirmesi ile aynı komutu cron ortamında test edin.
Crontab'da yüzde işareti neden bozar?
Crontab satırında kaçırılmamış % yeni satır sayılır; sonrasındaki metin komuta stdin olarak gider. date +%Y gibi ifadeleri \%Y olarak yazın veya karmaşık komutları bir script dosyasına taşıyın.
Cron Sorunlarından Kurtulun
cronjob.com.tr ile URL tabanlı işlerinizi panelden zamanlayın. PATH ve izin derdi olmadan log ve hata bildirimlerini görün. Ücretsiz; kayıtta kart istenmez.
Ücretsiz Başla →