Laravel Task Scheduling Zamanlanmış Görevler Rehberi

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

Laravel'de zamanlanmış görevi tanımlamak, sunucunun onu çağırdığı anlamına gelmez. Uygulama içindeki Scheduler hangi işin zamanı geldiğini seçer; sunucudaki cron ise bu kontrolü düzenli başlatır. Yanlış PHP yolu, farklı çalışma kullanıcısı veya kapalı kuyruk worker'ı yüzünden terminalde çalışan iş üretimde sonuç vermeyebilir.

Bu rehberde önce gerçek bir Artisan komutu oluşturacak, sonra tek cron kaydıyla çalıştıracak ve sonucunu dosyadan doğrulayacaksınız. Örnekler SSH erişimli Linux sunucuyu hedefler. SSH olmayan ortamlarda güvenli HTTP alternatifi ayrıca anlatılır. Temel zaman alanlarını öğrenmek için crontab sözdizimini inceleyebilirsiniz.

Scheduler, Cron ve Queue Arasındaki Fark

Cron işletim sistemi zamanlayıcısıdır. schedule:run çağrıldığında Laravel o anda zamanı gelen işleri değerlendirir. Bir Artisan komutu doğrudan çalıştırılıyorsa işlem scheduler sürecinde yürür. Kuyruğa iş gönderiliyorsa asıl işi bir worker tamamlar; scheduler'ın hatasız çıkması kuyruktaki işin tamamlandığını kanıtlamaz.

Yerelde schedule:work ile zamanlayıcıyı ön planda çalıştırabilirsiniz. Üretimde aynı iş için hem bu süreci hem cron kaydını başlatmayın. Dağıtımda birden fazla sunucu varsa hangi makinelerin zamanlayıcı çalıştıracağını açıkça belirleyin. Zamanlama davranışı için Laravel Scheduler belgesini projenizin sürümünü seçerek okuyun. Aynı ayrımı Ruby tarafında çözmek isteyenler için Rails cron job rehberimizde benzer zamanlayıcı ve kuyruk kararları ele alınıyor.

Adım Adım: Çalışan Bir Artisan Komutu Oluşturma

Örneğimiz son 24 saatte etkin olmuş veritabanı oturumlarının sayısını JSON raporuna yazar. Oturum sayısı tekil kullanıcı sayısı değildir; ziyaretçinin birden fazla oturumu olabilir. Kurulu Laravel uygulamanızda database session sürücüsü ve sessions tablosu bulunmalıdır. Farklı bir oturum sürücüsü kullanıyorsanız bu örneği doğrudan üretim tablonuza uygulamayın.

  1. Proje kökünde Laravel ve PHP sürümünü kontrol edin. Cron'da da aynı CLI PHP çalıştırılmalıdır; web sunucusunun PHP sürümü farklı olabilir.
  2. Artisan ile SessionReport komutunu oluşturun. Oluşan dosyanın içeriğini aşağıdaki sınıfla değiştirin.
  3. Komutu elle çalıştırın. Yerel depolama diskinizin reports/sessions.json dosyasını açın; tarih ve sayının beklendiği gibi olduğunu doğrulayın.
  4. Veritabanına erişimi ve depolama dizini izinlerini cron'u çalıştıracak uygulama kullanıcısıyla da kontrol edin.
php --version
php artisan --version
php artisan make:command SessionReport
php artisan app:session-report
<?php
// app/Console/Commands/SessionReport.php
namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;

class SessionReport extends Command
{
    protected $signature = 'app:session-report';
    protected $description = 'Son 24 saatte etkin oturumların sayısını kaydeder';

    public function handle(): int
    {
        $count = DB::table('sessions')
            ->where('last_activity', '>=', now()->subDay()->timestamp)
            ->count();

        $payload = json_encode([
            'generated_at' => now()->toIso8601String(),
            'active_sessions_24h' => $count,
        ], JSON_THROW_ON_ERROR);

        if (! Storage::disk('local')->put('reports/sessions.json', $payload)) {
            $this->error('Rapor yazılamadı');
            return self::FAILURE;
        }

        $this->info("Etkin oturum: {$count}");
        return self::SUCCESS;
    }
}

Standart uygulama yapısında app/Console/Commands altındaki komutlar otomatik kaydedilir. Özelleştirilmiş bir projede php artisan list çıktısında komutun bulunduğunu kontrol edin. Artisan komut belgesi, komut üretme, argümanlar ve çıkış kodları için başvuru kaynağıdır. Başarısızlığı yakalayıp sessizce başarı döndürmek yerine hatayı uygun çıkış koduyla görünür bırakın.

Sürüme Göre Zamanlama Dosyası ve Cron Kaydı

Laravel 11 ve sonrasında yeni uygulama iskeletinde tanımları genellikle routes/console.php içine yazarsınız. Laravel 10 ve eski yapıyı koruyan yükseltilmiş projelerde app/Console/Kernel.php kullanılabilir. Sadece sürüm numarasına bakıp çalışan yapıyı taşımayın; mevcut scheduler tanımlarının nerede yüklendiğini kontrol edin. Aynı görevi iki dosyada kaydetmeyin.

// routes/console.php; mevcut PHP açılış etiketinden sonra
use Illuminate\Support\Facades\Schedule;

Schedule::command('app:session-report')
    ->everyFiveMinutes()
    ->withoutOverlapping(10)
    ->appendOutputTo(storage_path('logs/session-report.log'));
// Eski uygulama yapısında app/Console/Kernel.php
protected function schedule(\Illuminate\Console\Scheduling\Schedule $schedule): void
{
    $schedule->command('app:session-report')
        ->everyFiveMinutes()
        ->withoutOverlapping(10);
}

Yukarıdaki iki seçenekten yalnızca projenize uygun olanını kullanın. Ardından uygulama kullanıcısının crontab kaydına aşağıdaki tek satırı ekleyin. /usr/bin/php yolunu sunucunuzdaki CLI PHP yolu ile, proje dizinini gerçek dağıtım yolu ile değiştirin. Kullanıcı crontab'ında ayrıca kullanıcı adı sütunu bulunmaz.

# crontab -e
* * * * * cd /var/www/laravel && /usr/bin/php artisan schedule:run >>/var/www/laravel/storage/logs/scheduler.log 2>&1

İlk doğrulamada çıktıyı /dev/null içine atmayın. Cron yalnızca her dakika Laravel'i uyandırır; beş dakikalık seçim uygulamanın içindedir. cPanel cron ayarında da dakika alanlarını her dakika olacak şekilde doldurun, panelin beklediği komut alanına yalnızca komut bölümünü girin. Hosting sağlayıcınızın PHP yolu ve izinleri örnek sunucudan farklı olabilir.

Gerçek Senaryolar ve Saat Dilimi Seçimi

Operasyon ekranı için oturum raporu: Beş dakikalık örnek, yönetim ekranında yakın zamandaki kullanımın izlenmesine uygundur. Dosyanın generated_at değeri eskiyse ekran bunu belirtmelidir. Hızlı yenileme uğruna her sayfa isteğinde aynı sayım sorgusunu çalıştırmak yerine raporu düzenli üretirsiniz. Tablo büyüdükçe last_activity alanının indeksini ve sorgu süresini inceleyin.

İş günü başlangıcında rapor: Aynı komutu her sabah Türkiye saatine göre 09:00'da üretmek istiyorsanız tanımı aşağıdakiyle değiştirin. Bu hâli yine son 24 saati kapsar; önceki takvim gününün raporu gerekiyorsa komutun tarih sınırlarını ayrıca değiştirmeniz gerekir. Zamanlama ile raporun veri dönemi ayrı kararlardır. Raporun ekipçe e-postayla paylaşılması gerekiyorsa cron e-posta gönderme rehberindeki kuyruk ve hız limiti önlemlerini bu tanımla birleştirin.

Schedule::command('app:session-report')
    ->dailyAt('09:00')
    ->timezone('Europe/Istanbul')
    ->withoutOverlapping(30);

Sunucu UTC kullanırken görevi belirli bir yerel saatte çalıştırabilirsiniz. Yaz saati uygulayan bölgelerde bazı saatler atlanabilir veya iki kez yaşanabilir; para ve faturalama işlerini sadece saate güvenerek yürütmeyin. Dönemi benzersiz kaydedin. Cron saat dilimi rehberi sunucu zamanı ile uygulama zamanı arasındaki farkı açıklamanıza yardımcı olur.

Çakışma, Çoklu Sunucu ve Kuyruk Yönetimi

withoutOverlapping(10) kilidin süre aşımını dakika olarak ayarlar; komutu on dakika sonra sonlandırmaz. Gerçek çalışma sürenizden kısa kilit süresi seçerseniz iş hâlâ devam ederken yeni kopya başlayabilir. Sunucu çökmesinden sonra kalan kilidi temizlemeden önce ilgili işin gerçekten durduğunu doğrulayın.

onOneServer için desteklenen merkezi cache sürücüleri database, memcached, dynamodb veya redis'tir; bütün sunucular aynı cache deposunu kullanmalıdır. Her makinede ayrı dosya cache'i paylaşılmış kilit oluşturmaz. Bu seçenek aynı tetiklemeyi tek sunucunun almasını sağlar; kuyruk işinin tekrar teslim edilmesine karşı iş mantığınız ayrıca korunmalıdır. Python tarafında benzer bir merkezî zamanlayıcıyı Django Celery Beat ile periodik görev tanımlama rehberimizdeki adımlarla kurabilirsiniz.

Ağır raporu bir queue job içine taşırsanız worker'ı servis yöneticisiyle sürekli çalıştırın. Scheduler kilidi kuyruğa gönderim tamamlandığında bırakılabilir; kuyruktaki uzun işin çakışmasını kendi iş kilidiyle önleyin. Worker deneme sayısı ve bekleme ayarları ile scheduler'ın bir sonraki çalışma zamanı farklı mekanizmalardır. Laravel kuyruk belgesi bu yaşam döngüsünü ve başarısız işler yönetimini açıklar.

Doğrulama ve Sık Hataların Çözümü

php artisan list
php artisan schedule:list
php artisan app:session-report
php artisan schedule:run
php artisan schedule:clear-cache

Son komut bakım amaçlıdır; rutin deneme sırasında çalıştırmayın. Önce doğrudan komutu, sonra zamanlama listesini, en son cron üzerinden sonucu kontrol edin. schedule:run yalnızca o anda zamanı gelen görevleri çalıştırır. Geceye tanımlı bir işin gündüz çalışmaması tek başına hata değildir. Gerektiğinde deneme ortamında zamanı geçici değiştirip sonucu doğrulayın.

Could not open input file: artisan

Çalışma dizini yanlış veya dağıtım yolu değişmiştir. Cron satırındaki cd hedefini ve artisan dosyasının varlığını kontrol edin. Sembolik bağlantıyla dağıtıyorsanız bağlantının yeni sürümü gösterdiğini doğrulayın.

/bin/sh: 1: php: not found

Cron ortamında PHP yolu bulunamıyordur. Mutlak CLI PHP yolunu kullanın ve aynı çalıştırılabilir dosyayla gerekli uzantıların yüklendiğini kontrol edin. Terminalinizdeki sürüm yöneticisinin cron tarafından otomatik yüklenmesini beklemeyin.

Permission denied

storage veya bootstrap/cache dizinleri cron kullanıcısına yazılabilir olmayabilir. Dosya sahipliğiyle servis kullanıcısını eşleştirin; log dosyası root tarafından oluşturulmuşsa uygulama kullanıcısı ekleme yapamayabilir. Bütün projeye 777 vermek yerine gereken dizin izinlerini düzeltin.

Command "app:session-report" is not defined

Komut sınıfı yanlış dizinde olabilir, signature farklı olabilir veya sunucuda eski dağıtım çalışıyordur. artisan list ile adı kontrol edin; dosyanın dağıtıma girdiğini ve sınıfın doğru namespace kullandığını doğrulayın. Cron'u değiştirmeden önce doğrudan çağrıyı düzeltin.

No scheduled commands are ready to run veya bekleyen işler

Bu mesaj her zaman hata değildir: zaman, ortam filtresi, bakım modu ve kilit koşullarını inceleyin. Bakım modunda görevler normalde atlanır. Kuyruk işleri bekliyorsa worker'ın doğru bağlantı ve kuyruğu tükettiğini kontrol edin. Sunucu tarafındaki genel kontroller için cron hata çözüm rehberine bakabilirsiniz.

cronjob.com.tr ile Güvenli HTTP Tetikleme

SSH erişimi olmayan ancak HTTPS uygulaması yayımlayabilen bir hostingte yalnızca belirli işi çağıran uç nokta kullanabilirsiniz. Bütün Artisan komutlarını kullanıcı girdisinden seçen genel bir endpoint açmayın. Aşağıdaki örnek API yönlendirmesi etkin projede routes/api.php içindir; önce route:list ile /api/internal/session-report adresini doğrulayın.

// config/services.php içindeki döndürülen diziye ekleyin
'cron' => [
    'token' => env('CRON_HTTP_TOKEN'),
],
// routes/api.php; mevcut PHP açılış etiketinden sonra
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Route;

Route::post('/internal/session-report', function (Request $request) {
    $expected = (string) config('services.cron.token', '');
    $given = (string) $request->header('X-Cron-Token', '');
    abort_if($expected === '' || ! hash_equals($expected, $given), 403);

    $lock = Cache::lock('http-session-report', 120);
    if (! $lock->get()) {
        return response()->json(['error' => 'already_running'], 409);
    }
    try {
        $exit = Artisan::call('app:session-report');
        return response()->json(
            ['status' => $exit === 0 ? 'completed' : 'failed'],
            $exit === 0 ? 200 : 500
        );
    } finally {
        $lock->release();
    }
});
  1. Sunucunun ortam ayarına uzun rastgele CRON_HTTP_TOKEN girin. Config cache kullanıyorsanız normal dağıtım işleminizle yapılandırmayı yenileyin. Token'ı kaynak koduna eklemeyin.
  2. Panelde tam HTTPS URL'sini ve POST metodunu seçin. X-Cron-Token header'ına gizli değeri yazın; hazır aralığı beş dakika olarak ayarlayın.
  3. Yanlış token ile 403, doğru token ile rapor ve 200 yanıtını doğrulayın. Aynı raporun cron tanımını kaldırın; iki yolun kilit adları kendiliğinden ortak değildir.

419 alırsanız çağrıyı yanlışlıkla CSRF korumalı web rotasına göndermiş olabilirsiniz; uygulamanın bütün CSRF korumasını kapatmayın. Kullandığınız sürümün API rota yapılandırmasını denetleyin. Örneğin kısa işlemi senkron tamamladığını, uzun işler için kuyruğa gönderim tasarlamanız gerektiğini dikkate alın; kilidin 120 saniyesi işlem süresini sınırlamaz.

cronjob.com.tr ücretsizdir ve en kısa aralığı 60 saniyedir. Hazır bir dakikalık aralıkta yanıt bekleme 55 saniye, beş dakika ve üzeri aralıklarda ve cron ifadeli işlerde 290 saniyedir. HTTP 200–399 ve bağlantı hatası olmaması başarı sayılır; 202 yanıtıyla kuyruğa kabul edilen işin sonraki hatası burada görülmez.

Varsayılan ardışık hata eşiği 3'tür ve 1–20 arasında ayarlanabilir. Eşik aşılınca erişim sorunu, düzelince kesinti süresiyle düzeldi e-postası gönderilir; aynı iş için bildirimler arasında en az 60 dakika bulunur. Kayıtlar 7 gün tutulur. Uç nokta herkese açık ağdan erişilebilir olmalıdır; özel ağ adreslerine istek gönderilmez ve HTTPS sertifikası doğrulanır.

Sıkça Sorulan Sorular (SSS)

Her Laravel görevi için ayrı cron satırı gerekli mi?

Hayır. Her dakika schedule:run çağıran tek kayıt yeterlidir; görevlerin farklı aralıklarını Laravel içinde tanımlarsınız. Birden fazla kayıt eklemek aynı işleri tekrar tetikleyebilir.

schedule:run kaçırılan bütün görevleri sonradan çalıştırır mı?

Hayır. Komut çalıştığı andaki zamanlama koşullarını değerlendirir. Kesinti sırasında kaçan rapor veya faturalama dönemlerini tamamlamak için uygulamanızda dönem kaydı ve telafi işlemi tasarlayın.

withoutOverlapping uzun görevi durdurur mu?

Hayır. Bu yöntem kilit alarak yeni kopyanın başlamasını sınırlar; parametresi kilidin dakika cinsinden süre aşımıdır. Çalışan işlemi sonlandırmak için ayrıca uygun süreç veya iş zaman aşımı gerekir.

Başarısız Artisan komutu otomatik tekrar denenir mi?

Scheduler aynı başarısız çalışmayı kendiliğinden yeniden denemez. Sonraki zamanlama yeni bir tetiklemedir. Yeniden deneme gerekiyorsa kuyruk işinin deneme politikasını veya açık bir telafi mekanizmasını yapılandırın.

HTTP yanıtı başarılıysa kuyruk işi bitmiş midir?

Hayır. Endpoint yalnızca işi kuyruğa koyuyorsa başarılı yanıt kabulü gösterir. Worker sonucunu, başarısız işler kaydını ve işin ürettiği çıktıyı ayrıca izlemelisiniz.

Laravel Uç Noktanızı Zamanlayın

cronjob.com.tr ile korumalı HTTPS görevinizi ücretsiz zamanlayın. Kayıtta kredi kartı istenmez.

Ücretsiz Başla →

İlgili Rehberler