كلاهما يشغّل شيئًا وفق جدول. والفرق يظهر حين تفشل مهمّة، أو تطول مهمّة، أو يكون الجهاز مطفأً في اللحظة التي حلّ فيها موعدها.
كرون وفخّاه
crontab -e
# m h dom mon dow command
15 3 * * * /usr/bin/php /var/www/site/cron.php >> /var/log/site-cron.log 2>&1
- البيئةُ شبه فارغة. فمتغيّر PATH أدنى ما يكون، وملفُّ صدفتك لا يُقرأ، فالأمرُ الذي يعمل حين تكتبه بنفسك يفشل هنا. استخدم مساراتٍ مطلقة.
- الخَرْجُ بريدٌ لا سجلّ. فبدون إعادة التوجيه أعلاه يذهب الخَرْج إلى صندوق بريدٍ محلّي لا يقرؤه أحد، فتبدو المهمّة كأنها عملت بصمت.
وإن بدت مهمّةُ كرون كأنها لا تعمل البتّة، فقائمةُ الفحص في مهامّ كرون التي لا تعمل أبدًا تغطّي ما بقي.
المؤقّت وما يضيفه
# /etc/systemd/system/site-cron.service
[Unit]
Description=Site maintenance
[Service]
Type=oneshot
User=www-data
WorkingDirectory=/var/www/site
ExecStart=/usr/bin/php cron.php
# /etc/systemd/system/site-cron.timer
[Unit]
Description=Run site maintenance nightly
[Timer]
OnCalendar=*-*-* 03:15:00
Persistent=true
RandomizedDelaySec=300
[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now site-cron.timer
systemctl list-timers --all
journalctl -u site-cron -n 50
ما يمنحك إيّاه المؤقّت
- سجلّاتٌ في اليوميّة، بحالة الخروج، لكل تشغيلة.
- ولا تداخل — فتشغيلةٌ ما زالت جارية حين يحلّ موعد التالية لا تبدأ نسخةً ثانية.
- وPersistent=true — فتشغيلةٌ فاتت والجهازُ مطفأ تقع عند الإقلاع التالي.
- وRandomizedDelaySec — فأسطولُ خوادم لا يقصد الواجهة نفسها كلُّه عند ٠٣:١٥:٠٠ بالضبط.
أيَّهما تستخدم
مهمّةٌ من سطرٍ واحد على جهازٍ واحد: كرون، ولا تُطِل التفكير. وأمّا كلُّ ما تحتاج أن ترى تاريخه، وكلُّ ما يجب ألّا يعمل مرّتين، وكلُّ ما يهمّ إن فات: فمؤقّت.
لا تجدوِل المهمّة نفسها في الاثنين. فتلك نتيجةٌ شائعة لهجرةٍ لم تكتمل، وهي تضاعف كل تشغيلة — بما فيها التي ترسل بريدًا أو تخصم من بطاقة.
