WP Cron ile WordPress’te Zamanlı Görev Yönetimi

WordPress kurulumunuzda işler beklenmedik şekillerde yavaşlamaya başladıysa, e-posta bildirimleri gecikmeli geliyorsa ya da WooCommerce siparişleri zamanında işlenmiyorsa, büyük ihtimalle WP-Cron mekanizmasında bir sorun vardır. WP-Cron, WordPress’in zamanlı görev yönetim sistemidir ve doğru yapılandırılmadığında ciddi performans sorunlarına yol açabilir. Bu yazıda WP-Cron’u WP-CLI aracılığıyla nasıl yöneteceğinizi, sorunları nasıl tespit edip çözeceğinizi ve production ortamında en iyi pratikleri nasıl uygulayacağınızı ele alacağız.

WP-Cron Nedir ve Nasıl Çalışır?

WP-Cron, WordPress’in dahili zamanlı görev sistemidir. Ancak Unix sistemlerindeki gerçek cron’dan temel bir farkı vardır: tetikleyici tabanlı çalışır. Yani bir görev, belirlenen zamandan sonra ilk site ziyareti gerçekleştiğinde çalışır. Sitenize kimse girmiyorsa, o görev asla tetiklenmez.

Bu mekanizma şu şekilde işler:

  • Bir kullanıcı siteyi ziyaret ettiğinde WordPress, wp-cron.php dosyasını arka planda HTTP isteğiyle çağırır
  • Bu dosya bekleyen zamanlanmış görevleri kontrol eder
  • Zamanı gelen görevler sırayla çalıştırılır
  • Her sayfa yüklemesi bu kontrolü tetikler, bu da yüksek trafikli sitelerde ciddi ek yük oluşturur

Düşük trafikli sitelerde görevler geç çalışır, yüksek trafikli sitelerde ise her istek cron kontrolü yaptığı için gereksiz kaynak harcar. Her iki senaryoda da WP-Cron’u WP-CLI ile aktif olarak yönetmek şarttır.

WP-CLI Cron Komutlarına Genel Bakış

WP-CLI, cron yönetimi için wp cron komut grubunu sunar. Temel alt komutlar şunlardır:

  • wp cron event list: Mevcut cron olaylarını listeler
  • wp cron event run: Belirli bir olayı manuel çalıştırır
  • wp cron event delete: Bir cron olayını siler
  • wp cron event schedule: Yeni bir cron olayı planlar
  • wp cron schedule list: Mevcut cron takvimlerini listeler
  • wp cron test: Cron sisteminin düzgün çalışıp çalışmadığını test eder

Şimdi bunları tek tek inceleyelim.

Mevcut Cron Görevlerini Listeleme

Bir sisteme ilk el attığınızda yapmanız gereken ilk şey mevcut durumu görmektir. Sitenizde hangi cron görevleri var, ne zaman çalışacaklar, hangi sıklıkta tekrarlanıyorlar?

wp cron event list

Bu komut çok fazla çıktı üretiyorsa filtreleme yapabilirsiniz:

# Sadece belirli bir hook'u filtrele
wp cron event list --fields=hook,next_run_gmt,schedule --format=table

# JSON formatında çıktı al (scriptlerde kullanmak için)
wp cron event list --format=json

# Belirli bir hook'u ara
wp cron event list | grep woocommerce

Gerçek hayatta bir müşteri sitesinde bu komutu çalıştırdığımda şu gibi çıktılarla karşılaştım:

wp cron event list --fields=hook,next_run_relative,schedule

Çıktıda wp_scheduled_delete hook’unun 3 gün gecikmiş olduğunu gördüm. Bu, cron sisteminin tamamen bozulduğunun açık göstergesiydi. Sitenin düşük trafikli olması nedeniyle hiçbir şey tetiklenmemişti.

Cron Sistemini Test Etme

Herhangi bir değişiklik yapmadan önce sistemin sağlıklı çalışıp çalışmadığını test edin:

wp cron test

Başarılı bir çıktı şöyle görünür: Success: WP-Cron spawning is working as expected.

Eğer hata alıyorsanız, büyük ihtimalle şu iki nedenden biridir: ya wp-cron.php‘ye HTTP erişimi engellenmiştir ya da DISABLE_WP_CRON sabiti true olarak ayarlanmıştır.

wp-config.php dosyasını kontrol edin:

grep -n "DISABLE_WP_CRON|ALTERNATE_WP_CRON" /var/www/html/wp-config.php

Cron Takvimlerini Görüntüleme

WordPress varsayılan olarak üç cron takvimi sunar: hourly, twicedaily ve daily. Eklentiler de kendi takvimlerini ekleyebilir.

wp cron schedule list

Çıktıda her takvimin adını, görünen adını ve interval değerini (saniye cinsinden) görebilirsiniz. Bu bilgi, görevlerin ne sıklıkta çalıştığını anlamak için kritiktir.

WooCommerce yüklü bir sitede genellikle şu ek takvimler görünür:

  • woocommerce_fifteen_minutes: 15 dakikada bir
  • woocommerce_half_hour: 30 dakikada bir

Eğer bu takvimler listede yoksa, eklentinin cron hook’larını düzgün kaydetmediği anlamına gelebilir.

Manuel Cron Çalıştırma

Bir görevi hemen tetiklemek istediğinizde, trafik beklemeden manuel çalıştırabilirsiniz:

# Belirli bir hook'u çalıştır
wp cron event run wp_scheduled_delete

# Tüm bekleyen cron görevlerini çalıştır
wp cron event run --due-now

--due-now parametresi, zamanı gelmiş tüm görevleri tek seferinde çalıştırır. Bakım moduna alınan bir siteyi tekrar açarken bu komut son derece kullanışlıdır. Biriken gecikmiş görevleri temizlemek için birebirdir.

Dikkat: Yüksek trafikli bir WooCommerce sitesinde --due-now parametresiyle onlarca görevi aynı anda tetiklemek, anlık bir yük artışına neden olabilir. Mümkünse bu işlemi düşük trafikli saatlerde yapın.

Gereksiz Cron Görevlerini Silme

Zamanla kaldırılan eklentilerin ardında “hayalet” cron görevleri kalabilir. Bu görevler çalıştırılmak istenir ama ilgili kod artık yoktur. En iyi ihtimalle hata loglarını şişirir, en kötü ihtimalle PHP fatal error’lara yol açar.

# Belirli bir hook'u sil
wp cron event delete wp_update_themes

# Birden fazla hook'u sil
wp cron event delete wp_update_themes wp_update_plugins

Örnek senaryo: Bir müşteri sitesinde elementor_pro_safe_mode adlı bir cron görevinin dakikada bir çalıştığını fark ettim. Elementor Pro kaldırılmış ama cron kaydı temizlenmemişti. Bu görev her dakika çalışıyor, ilgili sınıfı bulamıyor ve sessizce başarısız oluyordu. Aylarca böyle devam etmişti.

# Önce görevin var olup olmadığını doğrula
wp cron event list | grep elementor_pro_safe_mode

# Sonra sil
wp cron event delete elementor_pro_safe_mode

Yeni Cron Görevi Oluşturma

WP-CLI ile tek seferlik veya tekrarlayan cron görevleri oluşturabilirsiniz:

# Tek seferlik görev (Unix timestamp veya +1 hour formatı)
wp cron event schedule my_custom_hook $(date -d "+1 hour" +%s)

# Saatlik tekrarlayan görev
wp cron event schedule my_custom_hook now hourly

# Argümanlarla birlikte görev oluşturma
wp cron event schedule send_weekly_report now weekly '["[email protected]", "weekly"]'

Bu özellik özellikle geliştirme ve test süreçlerinde çok işe yarar. Haftalık çalışması gereken bir görevi hemen test etmek için now parametresiyle tetikleyebilirsiniz.

Production Ortamı: Sistem Cron’u ile WP-Cron’u Birleştirme

Bu yazının en kritik bölümüne geldik. Production ortamında WP-Cron’u HTTP tabanlı çalışma şeklinden kurtarıp gerçek sistem cron’uyla entegre etmek, hem güvenilirlik hem de performans açısından zorunludur.

Adım 1: wp-config.php dosyasına WP-Cron’u devre dışı bırakın:

wp config set DISABLE_WP_CRON true --raw

Bu komut, wp-config.php dosyasına define('DISABLE_WP_CRON', true); satırını ekler. Artık her sayfa yüklemesinde cron kontrolü yapılmaz.

Adım 2: Sistem cron’a WP-CLI komutu ekleyin:

crontab -e

Aşağıdaki satırı ekleyin:

*/5 * * * * cd /var/www/html && wp cron event run --due-now --path=/var/www/html --url=https://siteniz.com >> /var/log/wp-cron.log 2>&1

Bu yapılandırma şunları sağlar:

  • Her 5 dakikada bir WP-CLI zamanlanmış görevleri kontrol eder
  • Sayfa ziyaretine bağımlılık ortadan kalkar
  • Görevler tahmin edilebilir ve güvenilir şekilde çalışır
  • Loglar /var/log/wp-cron.log dosyasına yazılır

Multisite kurulumlar için her site ayrı URL parametresiyle çalıştırılmalıdır:

*/5 * * * * wp cron event run --due-now --path=/var/www/html --url=https://site1.com >> /var/log/wp-cron-site1.log 2>&1
*/5 * * * * wp cron event run --due-now --path=/var/www/html --url=https://site2.com >> /var/log/wp-cron-site2.log 2>&1

WooCommerce Özel Cron Görev Yönetimi

WooCommerce, kendi cron görevleri için Action Scheduler kütüphanesini kullanır. Bunlar standart WP-Cron görevlerinden farklıdır ancak WP-CLI üzerinden yönetilebilir.

WooCommerce cron görevlerini listelemek için:

# WooCommerce'e ait tüm cron görevlerini filtrele
wp cron event list | grep -E "woocommerce|wc_"

# WooCommerce veritabanı temizleme görevini kontrol et
wp cron event list | grep wc_cleanup_sessions

Kritik WooCommerce cron görevleri şunlardır:

  • woocommerce_cleanup_sessions: Oturum temizleme, varsayılan olarak günde bir çalışır
  • woocommerce_tracker_send_event: İstatistik gönderme (devre dışı bırakabilirsiniz)
  • wc_pending_stock_reduce: Bekleyen sipariş stok düşümü
  • woocommerce_geoip_updater: GeoIP veritabanı güncelleme

Eğer WooCommerce istatistik takibini devre dışı bırakmak istiyorsanız:

wp cron event delete woocommerce_tracker_send_event

Bu görev, anonim kullanım verilerini WooCommerce sunucularına gönderir. Privacy açısından hassas ortamlarda silinmesi tavsiye edilir.

Cron Görevlerini İzleme ve Loglama

Cron görevlerinin ne zaman çalıştığını ve ne kadar sürdüğünü izlemek, performans sorunlarını tespit etmek için şarttır. Basit bir izleme scripti:

#!/bin/bash
# /usr/local/bin/wp-cron-monitor.sh

SITE_PATH="/var/www/html"
SITE_URL="https://siteniz.com"
LOG_FILE="/var/log/wp-cron-detailed.log"
DATE=$(date '+%Y-%m-%d %H:%M:%S')

echo "[$DATE] Cron kontrolü başlıyor..." >> $LOG_FILE

# Bekleyen görev sayısını al
PENDING=$(wp cron event list --path=$SITE_PATH --url=$SITE_URL --format=count 2>/dev/null)
echo "[$DATE] Bekleyen görev sayısı: $PENDING" >> $LOG_FILE

# Bekleyen görevleri çalıştır ve süreyi ölç
START_TIME=$(date +%s)
wp cron event run --due-now --path=$SITE_PATH --url=$SITE_URL >> $LOG_FILE 2>&1
END_TIME=$(date +%s)

ELAPSED=$((END_TIME - START_TIME))
echo "[$DATE] Cron tamamlandı. Geçen süre: ${ELAPSED} saniye" >> $LOG_FILE
echo "---" >> $LOG_FILE

Bu scripti sistem cron’a ekleyin:

chmod +x /usr/local/bin/wp-cron-monitor.sh
crontab -e
# Şu satırı ekle:
*/5 * * * * /usr/local/bin/wp-cron-monitor.sh

Sorun Giderme: Yaygın WP-Cron Sorunları

Cron Görevleri Hiç Çalışmıyor

# İlk olarak test et
wp cron test

# wp-config.php kontrolü
wp config get DISABLE_WP_CRON

# wp-cron.php dosyasının erişilebilir olduğunu kontrol et
curl -I https://siteniz.com/wp-cron.php?doing_wp_cron

Eğer curl 403 veya 404 dönüyorsa, sunucu yapılandırmanızda wp-cron.php erişimi engellenmiş demektir. Bu durumda sistem cron yöntemi zaten zorunlu hale gelir.

Aynı Görev Birden Fazla Kez Kayıtlı

Bazen bir eklenti hatalı kodlanmış olduğunda aynı cron görevi defalarca kaydedilmiş olabilir. Bunu tespit etmek için:

wp cron event list --format=json | python3 -c "
import json, sys
from collections import Counter
events = json.load(sys.stdin)
hooks = [e['hook'] for e in events]
duplicates = {k: v for k, v in Counter(hooks).items() if v > 1}
for hook, count in duplicates.items():
    print(f'{hook}: {count} kayıt')
"

Duplicate görevleri temizlemek için ilgili hook’u silip yeniden oluşturmak gerekebilir:

wp cron event delete tekrar_eden_hook_adi
# Ardından eklentinin kendi kayıt mekanizmasını tetikle
wp plugin deactivate sorunlu-eklenti
wp plugin activate sorunlu-eklenti

Cron Görevleri Çok Uzun Sürüyor

Bazı cron görevleri gereksiz yere uzun sürebilir. Bunu tespit etmek için her görevi ayrı ayrı zamanlayabilirsiniz:

# Belirli bir hook'un ne kadar sürdüğünü ölç
time wp cron event run woocommerce_cleanup_sessions --path=/var/www/html

Eğer bir görev 30 saniyeden uzun sürüyorsa, ya eklenti kodunda sorun var ya da veritabanı optimize edilmesi gerekiyor.

Toplu Cron Yönetimi İçin Script

Birden fazla WordPress kurulumu yönetiyorsanız, tüm sitelerin cron sağlığını kontrol eden bir script son derece zaman kazandırır:

#!/bin/bash
# /usr/local/bin/check-all-wp-crons.sh

SITES=(
    "/var/www/site1:https://site1.com"
    "/var/www/site2:https://site2.com"
    "/var/www/site3:https://site3.com"
)

for SITE in "${SITES[@]}"; do
    PATH_PART=$(echo $SITE | cut -d: -f1)
    URL_PART=$(echo $SITE | cut -d: -f2-)
    
    echo "=== $URL_PART kontrol ediliyor ==="
    
    # Cron testi
    RESULT=$(wp cron test --path=$PATH_PART --url=$URL_PART 2>&1)
    if echo $RESULT | grep -q "Success"; then
        echo "Cron sistemi: OK"
    else
        echo "UYARI: Cron sistemi sorunlu! - $RESULT"
    fi
    
    # Bekleyen görev sayısı
    COUNT=$(wp cron event list --path=$PATH_PART --url=$URL_PART --format=count 2>/dev/null)
    echo "Bekleyen görev: $COUNT"
    
    # 1 günden eski bekleyen görevleri bul
    OVERDUE=$(wp cron event list --path=$PATH_PART --url=$URL_PART --format=json 2>/dev/null | 
        python3 -c "
import json, sys, time
events = json.load(sys.stdin)
now = time.time()
overdue = [e['hook'] for e in events if float(e.get('timestamp', now)) < now - 86400]
print(len(overdue))
" 2>/dev/null)
    
    if [ "$OVERDUE" -gt "0" ] 2>/dev/null; then
        echo "UYARI: $OVERDUE adet görev 1 günden fazla bekliyor!"
    fi
    
    echo ""
done

Güvenlik Notları

WP-Cron ile çalışırken göz ardı edilmemesi gereken birkaç güvenlik noktası vardır:

  • wp-cron.php’ye dış erişimi kısıtlayın: Sistem cron kullanıyorsanız, wp-cron.php dosyasına dışarıdan HTTP erişimini Nginx veya Apache yapılandırmasıyla engelleyin. Bu dosyaya erişim DOS saldırılarında kötüye kullanılabilir.
  • WP-CLI’ı doğru kullanıcıyla çalıştırın: Sistem cron’da WP-CLI komutunu web sunucusuyla aynı kullanıcı (genellikle www-data) olarak çalıştırın. Aksi halde dosya izin sorunları yaşarsınız.
  • Log dosyalarını izleyin: Cron loglarını düzenli kontrol edin. Beklenmedik hook isimleri kötü amaçlı eklenti aktivitesine işaret edebilir.
  • Zaman aşımı ayarları: Uzun süren cron görevleri için wp-config.php dosyasında set_time_limit değerini artırmak yerine, görevi daha küçük parçalara bölmeyi tercih edin.

Sonuç

WP-Cron, WordPress ekosisteminin çoğu kişinin farkında olmadığı ama her şeyi etkileyen kritik bir bileşenidir. WP-CLI olmadan bu sistemi yönetmek hem zahmetli hem de hata yapmaya açıktır. wp cron komut grubu ile bekleyen görevleri listeleyebilir, sorunlu hook’ları tespit edip temizleyebilir, sistem cron entegrasyonu yapabilir ve tüm bu işlemleri scriptlerle otomatize edebilirsiniz.

Production ortamında mutlaka DISABLE_WP_CRON ile dahili mekanizmayı kapatıp sistem cron üzerinden WP-CLI çalıştırmanızı öneririm. Bu değişiklik, hem sitenizin performansını iyileştirir hem de zamanlanmış görevlerin güvenilir şekilde çalışmasını garanti eder. WooCommerce kullanan sitelerde bu konfigürasyon neredeyse zorunludur çünkü sipariş işleme, stok yönetimi ve e-posta bildirimleri doğrudan bu mekanizmaya bağlıdır.

Birkaç dakika ayırıp wp cron event list çıktısını inceleyin. Büyük ihtimalle orada uzun süredir bekleyen veya gereksiz yere tekrarlayan bir şeyler bulacaksınız.

Bir yanıt yazın

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