حل مشكلة Laravel Scheduler وضبط Cron Job
شخّص توقف Laravel Scheduler باستخدام schedule:list وتشغيل الأمر كمستخدم Cron، ثم راجع المسارات والبيئة والتوقيت والأقفال وسجلات النظام.
أثبت أن Laravel سجل المهمة، ثم شغّل schedule:run بنفس مستخدم Cron. بعد ذلك استخدم Cron Entry واحدة بمسارات كاملة وافحص البيئة والتوقيت والـLocks.
يحتاج مجدول Laravel إلى سطر Cron واحد يعمل كل دقيقة، ثم يقرر Laravel المهام المستحقة. عند توقف مهمة، افصل بين ثلاثة احتمالات: تعريف الجدول داخل التطبيق، ونجاح أمر Artisan، وقدرة خدمة Cron في نظام التشغيل على استدعائه.
تأكد أن Laravel سجل المهمة
من مجلد الإصدار في الإنتاج:
cd /var/www/example/current
php artisan schedule:list
يجب أن ترى المهمة وموعد التشغيل التالي. بحسب إصدار Laravel وبنية المشروع ستوجد التعريفات عادة في routes/console.php أو Console Kernel.
نفذ:
php artisan schedule:run -vvv
هذا الأمر يشغل المهام المستحقة في اللحظة الحالية فقط. لا تتوقع تشغيل مهمة يومية في وقت غير موعدها. للاختبار أضف مؤقتاً Command آمنة تعمل كل دقيقة وتسجل Marker واضحاً، ثم احذفها.
إذا لم يقلع Artisan أصلح خطأ التطبيق أو Dependencies أو الصلاحيات قبل التحقيق في Cron.
اختبر الأمر كمستخدم Cron
بيئة SSH ليست مثل بيئة Cron. قد يختلف المستخدم، Working Directory، PATH، ونسخة PHP.
sudo -u www-data /usr/bin/php \
/var/www/example/current/artisan schedule:run -vvv
يحتاج المستخدم إلى قراءة ملفات Release والكتابة في storage وbootstrap/cache، والوصول إلى Database وCache والخدمات المستخدمة.
اعرف مسار PHP:
command -v php
/usr/bin/php -v
قد يستخدم Terminal إصداراً مختلفاً عن المسار الذي تستدعيه Cron.
أضف سطر Cron صحيحاً
داخل User Crontab عبر crontab -e:
* * * * * cd /var/www/example/current && /usr/bin/php artisan schedule:run >> /dev/null 2>&1
داخل /etc/crontab أو ملف في /etc/cron.d/ يجب إضافة اسم المستخدم:
* * * * * www-data cd /var/www/example/current && /usr/bin/php artisan schedule:run >> /dev/null 2>&1
لا تضع اسم المستخدم داخل User Crontab، وإلا سيعتبره النظام جزءاً من الأمر.
أثناء التشخيص لا ترسل المخرجات إلى /dev/null:
* * * * * cd /var/www/example/current && /usr/bin/php artisan schedule:run >> /var/log/example-scheduler.log 2>&1
اضبط ملكية السجل وLog Rotation، ولا تحتفظ بمخرجات قد تحتوي بيانات حساسة.
افحص خدمة Cron
في Ubuntu وDebian:
sudo systemctl status cron --no-pager
sudo journalctl -u cron --since "30 minutes ago"
في توزيعات تستخدم crond:
sudo systemctl status crond --no-pager
sudo journalctl -u crond --since "30 minutes ago"
وتأكد أن Entry موجودة للمستخدم المقصود:
sudo crontab -u www-data -l
عند استخدام Symlink باسم current تأكد أنه يشير إلى Release مكتملة بها .env وvendor.
راجع البيئة والتوقيت
Cron لا يقرأ بالضرورة متغيرات .profile. يجب أن يحصل Laravel على بيئته من إعداد الإنتاج المعتاد لا من جلسة Login.
إذا كان Config Cache فعالاً:
php artisan config:clear
php artisan config:cache
قارن Time Zone في نظام التشغيل وPHP وLaravel وأي Task لها Zone خاص. اختلاف التوقيت يجعل المهمة تعمل لكن في ساعة أخرى. وثق Clock المعتمد وانتبه إلى تغييرات Daylight Saving عند جدولة وقت محلي.
افحص أقفال withoutOverlapping وonOneServer
تستخدم withoutOverlapping() Cache Lock. بعد توقف سيرفر مفاجئ قد يبقى Lock حتى انتهاء مدته. بعد التأكد أنه لا توجد عملية حقيقية:
php artisan schedule:clear-cache
لا تنفذ الأمر كحل تلقائي كل دقيقة؛ قد يسمح بتشغيل نسختين من مهمة ما زالت تعمل.
في أكثر من Application Server تحتاج onOneServer() إلى Cache مشتركة تدعم Locks. File Cache محلية في كل Host لن تنسق بين السيرفرات.
إذا كانت المهمة أطول من تكرارها، قسمها أو أرسل Jobs صغيرة إلى Queue، ثم طبق دليل Laravel Queue وSupervisor.
اختبر المسار كاملاً
تأكد أن:
schedule:listيعرض الموعد الصحيح.schedule:runينجح كمستخدم Cron.- Journal يسجل استدعاء كل دقيقة.
- المهمة تسجل نتيجة ناجحة مرة واحدة.
- لا توجد عمليات متداخلة.
- Deploy جديد لا يكسر المسار أو البيئة.
راقب آخر وقت نجاح لكل مهمة مهمة. حالة خدمة Cron وحدها لا تثبت أن إرسال الفواتير أو النسخ الاحتياطي اكتمل.
أخطاء شائعة
تتكرر الأخطاء بسبب خلط صيغتي Crontab، مسار PHP نسبي، صلاحيات، Config Cache قديم، اختبار schedule:run خارج موعد المهمة، أو استخدام Cache غير مشتركة.
احفظ Cron Entry في توثيق البنية التحتية واختبر Scheduler بعد النشر. راجع نشر Laravel بدون توقف لتنسيق هذه الخطوات.
أسئلة شائعة
هل أستخدم schedule:work بدلاً من Cron؟
يفيد schedule:work كعملية أمامية في التطوير وبعض بنى Containers. في السيرفر التقليدي استخدم Cron Entry واحدة تستدعي schedule:run كل دقيقة.
هل يغني Supervisor عن Cron الخاصة بالـScheduler؟
لا. يدير Supervisor غالباً Queue Workers طويلة العمر. ما زال Scheduler يحتاج Cron، أو Process مجدولة ومراقبة صممتها عمداً لهذا الغرض.
مراجع رسمية
لديك سؤال عن هذا الدليل أو فكرة لتعاون تقني؟ تواصل مع بكري عبر المركز التقني.
نهاية الملاحظة.