Fehlerbehebung · Laravel
Laravel-Scheduler läuft nicht? Den stillen Ausfall beheben
Warum Laravels Scheduler still ausfällt — der fehlende Cron-Eintrag, falscher Benutzer, Umgebung und überlappende Tasks — und wie Sie es beheben.
Laravels Scheduler wird von einem einzigen System-Cron-Eintrag angetrieben. Ist der falsch — oder die Umgebung darunter — fallen alle geplanten Tasks still aus. Hier die Checkliste.
1. Der eine Cron-Eintrag muss existieren
Laravel braucht genau eine Crontab-Zeile, die schedule:run jede Minute aufruft.
Stellen Sie sicher, dass sie für den richtigen Benutzer existiert (meist Ihr
Deploy-Benutzer, nicht root):
crontab -l
Sie sollte lauten:
* * * * * cd /var/www/app && php artisan schedule:run >> /dev/null 2>&1
Fehlt sie, fügen Sie sie mit crontab -e hinzu. Ein häufiger Deploy-Fehler ist,
sie als root hinzuzufügen, während die App als www-data läuft (oder umgekehrt).
2. Nutzen Sie das richtige PHP-Binary und absolute Pfade
Unter Cron lässt sich php womöglich nicht auflösen oder ist die falsche Version.
Nutzen Sie den vollen Pfad und den Projektpfad:
* * * * * cd /var/www/app && /usr/bin/php8.3 artisan schedule:run >> /dev/null 2>&1
3. Die Umgebung unterscheidet sich von Ihrer Shell
Cron lädt Ihr Shell-Profil nicht, also fehlt alles, was Sie dort setzen. Laravel
liest .env, was in Ordnung ist — aber wenn Ihre Tasks andere Binaries aufrufen,
geben Sie ihnen einen expliziten PATH. Stellen Sie außerdem sicher, dass APP_ENV
sowie Queue-/Cache-Konfiguration zur Produktion passen.
4. Sie haben die Ausgabe unterdrückt und können nun nicht debuggen
>> /dev/null 2>&1 verbirgt alles, auch Fehler. Loggen Sie es vorübergehend:
* * * * * cd /var/www/app && php artisan schedule:run >> storage/logs/schedule.log 2>&1
Führen Sie dann php artisan schedule:run von Hand aus und lesen Sie die Ausgabe —
die meisten Fehler (Berechtigungen, fehlende Env, DB-Verbindung) zeigen sich sofort.
5. Tasks überlappen oder hängen
Ein langer Task, der jede Minute läuft, kann sich stauen. Nutzen Sie Laravels Guards, damit ein langsamer Lauf den nächsten nicht blockiert:
$schedule->command('reports:build')
->hourly()
->withoutOverlapping()
->onOneServer();
Das tiefere Problem: Der Scheduler kann stoppen und still bleiben
Stoppt schedule:run — der Server wurde neu gestartet, die Crontab beim Deploy
gelöscht, PHP aktualisiert — hat Laravel keine Möglichkeit, es Ihnen zu sagen. Ihre
in Queues eingereihten Reports und E-Mails hören einfach auf.
Pingen Sie einen Heartbeat aus einem geplanten Task, damit Sie wissen, dass der Scheduler selbst lebt:
$schedule->call(function () {
Http::timeout(10)->get('https://ping.steadycron.com/<ihr-ping-token>');
})->everyFifteenMinutes();
Bleibt dieser Ping aus, alarmiert Sie SteadyCron — der Scheduler ist down, bevor Ihre Nutzer es merken.