PHP ile Cron Job Oluşturma ve Çalıştırma Rehberi

PHPYayın: Güncellendi: 7 dk okumaHazırlayan: cronjob.com.tr Editörleri

PHP ile zamanlanmış iş (cron job) kurmak, kuyruk boşaltma, log temizliği, fatura üretimi veya bildirim gönderme gibi arka plan işlerini tarayıcıdan bağımsız çalıştırmanın standart yoludur. Sorun çoğu zaman script'te değil; yanlış PHP ikilisi, CLI ile FPM'in farklı php.ini dosyaları veya cron'un dar PATH ortamındadır.

Bu rehber, paylaşımlı hosting veya VPS'te PHP script'ini crontab sözdizimi ile güvenli çalıştırmayı adım adım anlatır. CLI yöntemi, HTTP tetikleme, gerçek hata mesajları ve sunucuya SSH erişiminiz yoksa cronjob.com.tr üzerinden URL tabanlı alternatif yer alır.

Hedef kitle: kendi sunucusunda veya cPanel'de PHP cron ekleyen geliştiriciler. Laravel kullanıyorsanız önce Laravel Task Scheduling rehberine bakın; orada tek satırlık schedule:run modeli geçerlidir. WHMCS gibi hazır faturalandırma yazılımı kullanıyorsanız cron komutunu tahmin etmek yerine panelin önerdiği satırdan almalısınız; WHMCS cron kurulum adımları ayrı rehberde anlatılır.

CLI mi, HTTP mi?

İki yaygın yöntem vardır. CLI, web sunucusunu (Apache/Nginx + PHP-FPM) bypass eder; daha hızlıdır, web timeout'una takılmaz ve dosya sistemi izinleri kullanıcı crontab'ına göre netleşir. HTTP yöntemi, script'in web uygulamasının bootstrap'ına, session'a veya reverse proxy kurallarına ihtiyaç duyduğu durumlarda tercih edilir.

ÖlçütPHP CLIHTTP (curl/wget)
Önerilen kullanımBatch, kuyruk, yedekUygulama içi endpoint
Zaman limitiCLI'da genelde sınırsızFPM/proxy timeout
GüvenlikWeb'e açılmazToken + HTTPS şart
Ortamcli php.inifpm php.ini
Not: Resmi php_sapi_name() belgesine göre komut satırından çağrılan php-cgi ikilisi cgi-fcgi döndürebilir. Cron satırında CLI ikilisinin mutlak yolunu kullanın (php.net).

Adım Adım Kurulum

  1. SSH ile sunucuya bağlanın. PHP CLI yolunu bulun: which php ve php -v. cPanel'de çoğu zaman /usr/local/bin/php CLI, /usr/bin/php ise CGI sarmalayıcısıdır.
  2. Script'i web kökünün dışında tutun (ör. /var/www/site/cron/temizlik.php). Web'den erişilecekse ayrı koruma ekleyin.
  3. Aynı kullanıcıyla manuel deneyin: /usr/bin/php /var/www/site/cron/temizlik.php. Çıktı ve çıkış kodu (echo $?) hatasız olmalı.
  4. crontab -e ile satırı ekleyin. Zaman ifadelerini cron ifade oluşturucu ile doğrulayabilirsiniz.
  5. Çıktıyı log'a yönlendirin: >> /var/log/cron-php.log 2>&1. Sessiz başarısızlıkları yakalamanın en pratik yoludur.
  6. İlk tetiklemeyi bekleyin veya dakikalık test satırı koyup log'u izleyin. İş bitince aralığı üretim değerine çekin.
# PHP yolunu doğrula
which php
php -v
php --ini

# Crontab örneği (her 15 dakikada)
*/15 * * * * /usr/bin/php /var/www/site/cron/kuyruk-isle.php >> /var/log/cron-php.log 2>&1

PHP Cron Script Yazma

Temel şablon

CLI kontrolü, sınırsız çalışma süresi, hata logu ve __DIR__ ile mutlak yollar production için minimum settir.

<?php
/**
 * Cron: günlük log temizliği
 * Zamanlama: 0 3 * * *
 */

if (php_sapi_name() !== 'cli') {
    http_response_code(403);
    die('Bu script sadece CLI üzerinden çalıştırılabilir.');
}

set_time_limit(0);
ini_set('memory_limit', '256M');
error_reporting(E_ALL);
ini_set('display_errors', '0');
ini_set('log_errors', '1');
ini_set('error_log', __DIR__ . '/../logs/cron-error.log');

require_once __DIR__ . '/../config/database.php';

function cronLog(string $message): void {
    echo '[' . date('Y-m-d H:i:s') . "] $message\n";
}

try {
    cronLog('Temizlik başladı');
    $pdo = new PDO($dsn, $dbUser, $dbPass, [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    ]);
    $stmt = $pdo->prepare(
        'DELETE FROM activity_logs WHERE created_at < DATE_SUB(NOW(), INTERVAL 90 DAY)'
    );
    $stmt->execute();
    cronLog($stmt->rowCount() . ' kayıt silindi');
    exit(0);
} catch (Throwable $e) {
    cronLog('HATA: ' . $e->getMessage());
    exit(1);
}

HTTP endpoint şablonu

HTTP kullanıyorsanız anahtarı sorguda değil header'da tutun; anahtarı kodda sabitlemeyin.

<?php
$beklenen = getenv('CRON_SECRET');
$gelen = $_SERVER['HTTP_X_CRON_TOKEN'] ?? '';
if (!$beklenen || !hash_equals($beklenen, $gelen)) {
    http_response_code(403);
    header('Content-Type: text/plain; charset=utf-8');
    echo 'Yetkisiz';
    exit;
}
// iş mantığı...
http_response_code(200);
echo 'OK';

Gerçek Senaryolar

Senaryo 1: E-posta kuyruğu (her 5 dakika)

Bekleyen kayıtları küçük paketlerle işlersiniz; tek seferde binlerce SMTP çağrısı sunucuyu ve sağlayıcı limitlerini zorlar. Zamanlama: */5 * * * *. Script her çalıştırmada LIMIT 50 alır, gönderir, durum günceller. Çakışmayı önlemek için dosya kilidi (flock) veya veritabanı kilidi kullanın. Paket boyutu, SMTP hız limiti ve başarısız kayıtların yeniden denenmesi dahil cron tabanlı e-posta kuyruğu kurulumunun tamamı ayrı rehberde işlenir.

*/5 * * * * /usr/bin/php /var/www/site/cron/email-kuyruk.php >> /var/log/email-cron.log 2>&1

Senaryo 2: Gece rapor ve arşiv (03:00)

Günlük sipariş özetini üretir, CSV yazar, isteğe bağlı e-posta ekler. Yoğun trafik saatlerinden kaçınmak için gece çalıştırılır: 0 3 * * *. Uzun süren dump işlemlerinde CLI tercih edin; HTTP proxy 60–120 sn timeout ile kesebilir. Sipariş ve stok görevlerinin bir e-ticaret sitesinde topluca nasıl kurgulandığını e-ticaret cron job rehberinde bulabilirsiniz; geceleyin dump alıp rotasyonla saklamanız gerekiyorsa cron ile veritabanı yedekleme şablonları daha uygundur.

Sık Hatalar ve Çözümleri

/bin/sh: 1: php: not found

Neden: Cron'un PATH'inde php yoktur. Çözüm: Mutlak yol yazın: /usr/bin/php veya /usr/local/bin/php.

Could not open input file: cron.php

Neden: Göreli yol; cron çalışma dizini genelde home'dur. Çözüm: Script yolunu mutlak verin veya cd /var/www/site && /usr/bin/php cron/temizlik.php kullanın.

PHP Fatal error: Uncaught PDOException: could not find driver

Neden: CLI php.ini'de PDO sürücüsü kapalı; FPM'de açıktır. Çözüm: php -m | grep -i pdo ve php --ini ile CLI eklentilerini kontrol edin; eksik paketi CLI için kurun.

Allowed memory size of 134217728 bytes exhausted

Neden: CLI varsayılan bellek limiti (ör. 128M) batch için yetmez. Çözüm: Script'te ini_set('memory_limit', '512M') veya crontab'ta php -d memory_limit=512M.

SAPI cgi-fcgi, CLI beklerken script reddediliyor

Neden: Yanlış ikili. Çözüm: /usr/local/bin/php -r 'echo PHP_SAPI, PHP_EOL;' çıktısının cli olduğundan emin olun.

Bu PATH ve ikili seçimi sorunları PHP'ye özgü değildir; Ruby on Rails tarafında bir rake görevini cron'a bağlarken de aynı mutlak yol disiplini geçerlidir. Rails tarafında zamanlanmış görev kurulumu bu ekosistemdeki karşılıklarını ayrıntılandırır.

Güvenlik ve Sürüm Seçimi

CLI script'lerini document root dışına koyun. HTTP endpoint'lerde gizli token'ı header'da taşıyın, HTTPS zorunlu tutun, mümkünse IP allowlist ekleyin. Apache'de dizin erişimini kısıtlayın; Nginx'te location ile engelleyin.

# Belirli sürüm örnekleri
*/15 * * * * /usr/bin/php8.2 /var/www/site/cron.php
*/15 * * * * /opt/cpanel/ea-php83/root/usr/bin/php /var/www/site/cron.php

Yukarıdaki ea-php83 yolu cPanel MultiPHP kurulumlarına özgüdür; DirectAdmin'de ise CustomBuild'a göre birden fazla PHP sürümü /usr/local/php* dizinlerinde tutulur ve CLI yolu panel türüne göre değişir. Yol yapısının tamamı DirectAdmin cron job kurulum rehberinde anlatılır.

İş çalışmıyorsa cron job çalışmıyor kontrol listesine ve cPanel cron adımlarına bakın.

cronjob.com.tr ile HTTP Alternatifi

Sunucuda crontab düzenleyemiyorsanız veya dışarıdan izlenen bir tetikleyici istiyorsanız, PHP işinizi korumalı bir HTTPS endpoint olarak yayınlayıp cronjob.com.tr ile çağırabilirsiniz. Hizmet ücretsizdir; kayıtta kredi kartı istenmez. En kısa aralık 60 saniyedir.

  1. Endpoint'i X-Cron-Token (veya HTTP Basic Auth) ile koruyun; yanıt olarak 2xx/3xx dönün.
  2. Panelde yeni iş: URL, metot (GET/POST), özel header, isteğe bağlı gövde.
  3. Zamanlama: hazır aralık veya 5 alanlı cron ifadesi; saat dilimi iş bazında (varsayılan Europe/Istanbul).
  4. Timeout aralığa göre ayarlanır (1 dk → 55 sn, 5 dk ve üzeri → 290 sn). Başarı: HTTP 200–399 ve bağlantı hatası olmaması.
  5. Ardışık hata eşiği aşılınca e-posta bildirimi gelir; loglarda durum kodu, süre ve yanıt gövdesinin ilk ~64 KB'ı 7 gün saklanır.

User-Agent: CronJobComTr/1.0 (+https://cronjob.com.tr). Yerel/özel ağ adreslerine istek gönderilmez; geçerli HTTPS sertifikası gerekir.

# Panelde header örneği
X-Cron-Token: uzun-rastgele-gizli-deger

Sıkça Sorulan Sorular (SSS)

PHP cron script'i web tarayıcıdan da çalıştırılabilir mi?

Güvenlik açısından önerilmez. CLI kontrolü (php_sapi_name() !== 'cli') ekleyerek web erişimini engelleyin. HTTP üzerinden çalıştırmanız gerekiyorsa gizli token, HTTPS ve mümkünse IP kısıtlama kullanın.

include ve require yolları cron'da neden bozulur?

Cron, çalışma dizinini script'in bulunduğu klasöre ayarlamaz. __DIR__ ile mutlak yol kullanın veya script başında chdir(__DIR__) çağırın.

CLI'da max_execution_time sınırlı mı?

CLI modunda varsayılan genelde 0'dır (sınırsız). Yine de set_time_limit(0) eklemek ve uzun işleri timeout ile sarmalamak iyi pratiktir.

php_sapi_name neden cgi-fcgi döner?

Crontab'ta CGI ikilisi çağrılıyor olabilir. which php ve php -v ile CLI ikilisini doğrulayın; cPanel'de çoğu zaman /usr/local/bin/php CLI'dır.

Cron'da .env değişkenleri neden boş gelir?

Cron minimal ortam kullanır. Değerleri crontab'ın başında KEY=deger biçiminde tanımlayın, dotenv yükleyin veya komut satırında KEY=deger öneki kullanın.

Hemen Ücretsiz Cron Job Oluşturun

cronjob.com.tr ile HTTPS URL'nizi zamanlayın. Ücretsizdir, kayıtta kredi kartı istenmez; en kısa aralık 1 dakikadır.

Ücretsiz Başla →

İlgili Rehberler