Cron job'u kaydettiniz, beklediniz ve hiçbir şey olmadı. Ne bir e-posta geldi, ne bir dosya oluşturuldu, ne de veritabanına bir kayıt eklendi. İşte tam da bu anda cron job hosting'in nasıl çalıştığını ve neden sessiz kaldığını anlamanız gerekiyor. Sorun neredeyse her zaman şu üç şeyden biridir: yanlış yol, hatalı zamanlama sözdizimi veya hiçbir yere gitmeyen ve göremediğiniz bir çıktı.
PHP'nin mutlak yolu; çoğu cron job'un öldüğü yer
Kontrol panelinde Command alanını php /home/user/public_html/cron.php ile dolduruyorsunuz ve işin bittiğini düşünüyorsunuz. Bitmedi. Cron, PATH'i sizin etkileşimli shell'inizden farklı olan bir ortamda çalışır. php hiç bulunamayabilir veya sitenin üzerinde çalıştığı sürümle aynı olmayan bir sürüm bulunabilir.
Önce binary'nin gerçek yolunu bulun:
which php
# /usr/local/bin/php
php -v
# PHP 8.2.18 (cli)
Sonra aynı mutlak yolu Command'a yazın:
/usr/local/bin/php /home/username/public_html/cron.php
Site PHP 8.2 üzerinde çalışıyorsa ve CLI 7.4 ise, betiğiniz bir parse hatasıyla ölebilir ve siz o hatayı asla göremezsiniz. Bu sürüm farkı, "çalışıyor ama sonuç vermiyor" durumunun en yaygın nedenlerinden biridir.
Göreli yol neden çalışmaz
Cron, betik klasörüyle değil $HOME çalışma klasörüyle çalışır. Kod içinde require 'config.php' kullandıysanız, dosya bulunamaz. Her zaman mutlak yol verin veya başta chdir(__DIR__) yapın.
Zamanlama sözdizimi: herkesin yanlış okuduğu beş yıldız
Standart biçim beş alana sahiptir: dakika, saat, ayın günü, ay, haftanın günü. Sırayı koruyun ve "her beş dakikada bir" için */5 * * * * yazın. "Her gece saat 3'te" için 0 3 * * * yazın.
| İfade | Anlamı | Yaygın kullanım |
|---|---|---|
*/5 * * * * | Her 5 dakikada bir | Hafif senkronizasyon |
0 * * * * | Her saatin başında | Önbellek temizleme |
0 3 * * * | Her gün saat 3'te | Veritabanı yedeği |
0 0 1 * * | Her ayın ilkinde | Aylık rapor |
0 4 * * 0 | Pazarları saat 4'te | Haftalık güncelleme |
Daha az söylenen bir nokta: ayın günü ve haftanın günü alanları AND değil OR ile birleşir. 0 0 1 * 0 yazarsanız, betik hem ayın ilkinde hem de her Pazar çalışır. Yalnızca ayın ilki Pazar günlerine denk geldiğinde çalışmasını istiyorsanız, koşulu kod içinde kontrol etmelisiniz.
Burada hata yapıyorlar
En çok gördüğüm hata şu: kullanıcı "hızlıca test etmek" için zamanlamayı * * * * * olarak ayarlıyor, sonra değiştirmeyi unutuyor. Belirtisi de açık; sunucu logu tekrarlayan girdilerle doluyor, hosting kaynak tüketimi artıyor ve site yavaşlıyor. Kaynak sınırlarını bilmiyorsanız, herhangi bir testten önce eksiksiz hosting kaynak sınırları referansını okuyun ki her sayının neyi saydığını anlayın.
Çıktıyı alın, yoksa kör kalırsınız
Cron varsayılan olarak çıktıyı size e-posta ile gönderir, ancak bu e-posta genellikle spam'e düşer veya hiç gönderilmez. Daha güvenilir yol, çıktıyı dosyaya yönlendirmektir:
/usr/local/bin/php /home/username/public_html/cron.php >> /home/username/cron.log 2>&1
Artık 2>&1 sayesinde stderr hataları da aynı dosyaya yazılır. Dosya boş kaldıysa, betik çalışmış ve hata vermemiş demektir. Dosya hiç oluşturulmadıysa, cron o satıra ulaşmamış ve sorun yolda veya zamanlamadadır.
Uzun süren betikler için, eşzamanlı çalışmayı önlemek amacıyla dosya kilidi de koyun:
*/10 * * * * /usr/bin/flock -n /tmp/mycron.lock /usr/local/bin/php /home/username/public_html/cron.php >> /home/username/cron.log 2>&1
Bu kilit olmadan, önceki çalışma henüz bitmemişse sonraki sürüm aynı veritabanına düşer ve yinelenen kayıtlar oluşturur. Bunu API senkronizasyonlarında çok gördüm.
Paylaşımlı hosting cron job'u ile özel sunucu karşılaştırması
Paylaşımlı hosting'de cron kısıtlı bir ortamda çalışır. Eşzamanlı çalışma sayısı sınırlıdır ve ağır betikler iş ortasında kesilebilir. İşiniz görüntü işleme, ağır içe aktarma veya binlerce kaydı tarama ise, bu ortam uygun yer değildir.
Burada gerçek bir seçim var. Hafif ve periyodik işler için aynı paylaşımlı hosting yeterlidir ve yönetimi daha kolaydır. Ağır işlemler veya her dakika çalıştırma için özel sunucuya veya VPS'ye geçin; orada hem tam kontrole sahipsiniz hem de cron yerine daha iyi loglama ve hata yönetimine sahip systemd timer koyabilirsiniz. Ben bir dakikanın altındaki her şey için systemd'yi tercih ediyorum.
Eşzamanlı çalışma sınırını ciddiye alın
Birkaç ağır cron job'u üst üste koyarsanız, Entry Process üst sınırına çarpabilirsiniz ve site ziyaretçiler için yavaşlar veya yanıt vermez. Bu kavramın normal ziyaretten farkını Entry Process açıklaması ve ziyaretten farkı yazımızda ele aldık. Basit çözüm: zamanlamaları dağıtın. Biri saat 2'de, biri 3'te, biri 4'te.
Cron çalışmadığında sorun giderme kontrol listesi
- PHP binary'sinin mutlak yolunu
which phpile doğrulayın. - Betik dosyasının mutlak yolunu tam olarak yazın.
- Çıktıyı dosyaya yönlendirin ve bir döngüden sonra dosyayı okuyun.
- Betiği SSH'den elle çalıştırın:
/usr/local/bin/php /home/username/public_html/cron.php. Elle de çalışmıyorsa sorun cron değil, koddur. - Dosya izinlerini kontrol edin; dosya hosting kullanıcısı tarafından okunabilir olmalıdır.
- Betik veritabanına bağlanıyorsa, genel IP yerine
localhostkullanın.
Dördüncü adımı ciddiye alın. Bize ulaşan ticket'ların yarısı, elle çalıştırmadan sonra betiğin baştan kod hatası olduğu ve cron'un suçsuz olduğu ortaya çıkıyor. PHP hatası alıyorsanız, beyaz ekran giderme ve PHP hata ayıklama kılavuzu iyi bir başlangıç noktasıdır.
WordPress ve yaygın işler için cron
WordPress'in kendi iç zamanlama sistemi vardır (WP-Cron) ve bu kullanıcı ziyaretiyle tetiklenir. Site trafiği düşükse, bu sistem geç çalışır. Standart çözüm, WP-Cron'u devre dışı bırakıp gerçek cron ile çağırmaktır:
# wp-config.php içinde
define('DISABLE_WP_CRON', true);
# cron job içinde
*/15 * * * * /usr/local/bin/php /home/username/public_html/wp-cron.php >> /home/username/cron.log 2>&1
Veritabanı yedeği için de doğrudan mysqldump çekmeyin; önce çıktıyı geçici bir dosyaya verin, sonra sıkıştırın, yoksa büyük veritabanlarında bellek üst sınırına çarparsınız.
Siteyi yeni kaldırdıysanız ve henüz klasör yapısına alışkın değilseniz, siteyi hosting'e yükleme kılavuzu yolları netleştirir. Ağ ve DNS testleri için de ücretsiz web yöneticisi araçları işi hızlandırır.
Linux hosting üzerinde çalışıyorsanız, kontrol panelindeki Cron Jobs bölümü bu satırları girdiğiniz yerdir; sadece her değişiklikten sonra bir kez çıktıyı kontrol etmeyi unutmayın.
Sık sorulan sorular
Cron job çalışıyor ama neden hiçbir sonuç görmüyorum?
Neredeyse her zaman şuna dayanır: betik çalışır ama hata verir ve hata hiçbir yere kaydedilmez. Çıktıyı >> /home/username/cron.log 2>&1 ile dosyaya yönlendirin ve tam bir döngüden sonra dosyayı okuyun. Dosya boşsa, betik hatasız çalışmıştır ve sorun kod mantığında veya veritabanı bağlantısındadır.
Cron job'daki PHP yolunu nereden öğrenirim?
SSH'de which php komutuyla. Çıktı genellikle /usr/local/bin/php gibi bir şeydir. Aynı mutlak yolu Command alanına yazın. CLI sürümü sitenin üzerinde çalıştığı sürümden farklıysa, php -v ile kontrol edin ve gerekirse doğru sürümün yolunu verin.
Cron job'u her dakika çalıştırabilir miyim?
Teknik olarak evet, ama paylaşımlı hosting'de önermem. Her dakika çalıştırma kaynakları tüketir ve betik ağırsa Entry Process üst sınırına çarpıp site yavaşlar. Gerçekten zaman açısından kritik işler için özel sunucu veya VPS daha doğru bir seçimdir.
WP-Cron ile sunucu cron job'u arasındaki fark nedir?
WP-Cron her kullanıcı ziyaretiyle tetiklenir, bu yüzden düşük trafikli sitelerde geç veya hiç çalışmaz. Sunucu cron job'u ise ziyaretten bağımsız olarak sizin zamanlamanıza göre çalışır. Ciddi siteler için WP-Cron'u devre dışı bırakın ve onu gerçek cron ile çağırın.
Şimdi bir şey yapın: cron çıktısını dosyaya yönlendirin ve bir döngü bekleyin. O dosyayı görmediğiniz sürece, diğer her değişiklik tahminden ibarettir.