Dépannage · Laravel

Le scheduler Laravel ne tourne pas ? Corrigez l’échec silencieux

Pourquoi le scheduler de Laravel s’arrête en silence — l’entrée cron manquante, le mauvais utilisateur, l’environnement et les tâches qui se chevauchent — et comment y remédier.

Le scheduler de Laravel est piloté par une seule entrée cron système. Si elle est incorrecte — ou l’environnement sous-jacent — toutes les tâches planifiées s’arrêtent en silence. Voici la checklist.

1. L’unique entrée cron doit exister

Laravel a besoin d’exactement une ligne de crontab appelant schedule:run chaque minute. Vérifiez qu’elle existe pour le bon utilisateur (généralement votre utilisateur de déploiement, pas root) :

crontab -l

Elle doit être :

* * * * * cd /var/www/app && php artisan schedule:run >> /dev/null 2>&1

Si elle manque, ajoutez-la avec crontab -e. Une erreur de déploiement courante est de l’ajouter en tant que root alors que l’app tourne en tant que www-data (ou inversement).

2. Utilisez le bon binaire PHP et un chemin absolu

Sous cron, php peut ne pas se résoudre, ou être la mauvaise version. Utilisez le chemin complet et celui du projet :

* * * * * cd /var/www/app && /usr/bin/php8.3 artisan schedule:run >> /dev/null 2>&1

3. L’environnement diffère de votre shell

Cron ne charge pas votre profil shell, donc tout ce que vous y définissez manque. Laravel lit .env, ce qui est bien — mais si vos tâches appellent d’autres binaires, donnez-leur un PATH explicite. Assurez-vous aussi que APP_ENV et la configuration des files/cache correspondent à la production.

4. Vous avez masqué la sortie et ne pouvez plus déboguer

>> /dev/null 2>&1 cache tout, y compris les erreurs. Journalisez-la temporairement :

* * * * * cd /var/www/app && php artisan schedule:run >> storage/logs/schedule.log 2>&1

Puis exécutez php artisan schedule:run à la main et lisez la sortie — la plupart des échecs (permissions, env manquant, connexion BD) apparaissent immédiatement.

5. Les tâches se chevauchent ou se bloquent

Une tâche longue qui tourne chaque minute peut s’accumuler. Utilisez les garde-fous de Laravel pour qu’une exécution lente ne bloque pas la suivante :

$schedule->command('reports:build')
    ->hourly()
    ->withoutOverlapping()
    ->onOneServer();

Le problème de fond : le scheduler peut s’arrêter et rester silencieux

Si schedule:run cesse de se déclencher — le serveur a redémarré, la crontab a été effacée au déploiement, PHP a été mis à jour — Laravel n’a aucun moyen de vous le dire. Vos rapports et e-mails en file s’arrêtent tout simplement.

Envoyez un ping heartbeat depuis une tâche planifiée pour savoir que le scheduler lui-même est vivant :

$schedule->call(function () {
    Http::timeout(10)->get('https://ping.steadycron.com/<votre-jeton-ping>');
})->everyFifteenMinutes();

Si ce ping manque, SteadyCron vous alerte — le scheduler est en panne, avant que vos utilisateurs ne s’en aperçoivent.