SSD Nodes Learn Hosting plans →
الأدلة Matt Connorبقلم Matt Connor · آخر تحديث في 2026-09-04

لماذا لا تعمل مهمة cron لديك؟ خمسة أسباب شائعة

اكتشف لماذا تفشل مهمة cron: PATH محدود، أو رمز % غير مُهَرَّب، أو crontab خاطئ، أو مخرجات تصل بالبريد، أو سكربت يعتمد على shell.

لماذا لا تعمل مهمة cron

مهمة cron التي «لا تعمل مطلقاً» تكون قد عملت في معظم الحالات. لقد عملت في بيئة تختلف عن بيئة shell لديك، ثم فشلت خلال الثانية الأولى، وأُرسلت الرسالة إلى مكان لا تقرأه. تفسّر خمسة أسباب تقريباً كل بلاغات هذه المشكلة: مسار البحث، والرمز المئوي، وملف crontab الخاطئ، والمخرجات التي أُرسلت بالبريد، والبرنامج النصي الذي يتوقع جلسة تسجيل دخول.

cron هو daemon (خدمة تعمل في الخلفية) يقرأ ملفات crontab ويبدأ الأوامر وفق جدول زمني. لا يقرأ .bashrc، ولا يفتح طرفية، ولا يبدأ login shell، ولا يخبرك عند فشل أمر. كل سبب مما يلي ناتج عن هذه الحقائق الأربع.

تعامل معها بالترتيب، وابدأ بالسؤال الذي يجمعها كلها: هل شغّل cron المهمة أصلاً؟ «لم يبدأ cron المهمة مطلقاً» و«بدأت المهمة ثم توقفت» مشكلتان مختلفتان لا تشتركان في شيء، لذلك أجب عن هذا السؤال أولاً.

هل نفّذ cron المهمة أصلاً؟

يحمل البرنامج الخفي اسماً مختلفاً للوحدة في عائلات التوزيعات المختلفة. تحقّق من الاسمين، ثم اقرأ السجل.

systemctl status cron
systemctl status crond
journalctl -u cron --since "2 hours ago"
journalctl -u crond --since "2 hours ago"

تسمّي Debian وUbuntu الوحدة cron. وتسمّيها Fedora وRocky وAlma crond. لا يوجد إلا أحد هذين الاسمين على الجهاز الواحد، لذلك من الطبيعي أن يُبلغ أحد الأمرين عن وحدة غير معروفة، ولا يعني ذلك وجود عطل.

اقرأ الإدخالات التي كتبها نظامك نفسه. لا تبحث عن سطر منسوخ من دليل، لأن الصياغة تختلف بين تطبيقات cron وبين إعدادات التسجيل المختلفة. تتحقق من أمرين فقط: هل يوجد إدخال في الدقيقة التي يحددها الجدول، وهل يسمّي ذلك الإدخال أمرك. وجود إدخال يسمّي أمرك يعني أن cron نفّذ الجزء الخاص به، وأن الفشل داخل الأمر. عدم وجود أي إدخال يعني أن cron لم يتلقَّ جدولك، وهذا هو السبب 3 أدناه.

ترسل بعض الصور رسائل cron عبر rsyslog إلى ملف بدلاً من journal. ابحث في /var/log عن ملف يحمل اسماً مرتبطاً بـcron أو syslog، ثم اقرأ نهايته.

ls -l /var/log
sudo tail -n 50 /var/log/syslog

إذا لم تكن الوحدة ولا السجل موجودين، فقد لا يكون cron مثبتاً أصلاً. غالباً ما تستبعد الصور السحابية المصغّرة والحاويات هذه الحزمة.

dpkg -l cron
rpm -q cronie
sudo apt install cron
sudo dnf install cronie
sudo systemctl enable --now cron

السبب 1: لا يملك cron قيمة PATH الخاصة بك

تنشئ الصدفة التفاعلية لديك PATH انطلاقاً من /etc/profile و~/.profile و~/.bashrc، ومن كل ما تستورده هذه الملفات. لا يُشغَّل أيٌّ من ذلك عند تنفيذ مهمة cron. يبدأ cron الأمر باستخدام بيئة مختصرة خاصة به، لذلك لا يعثر على البرنامج الموجود خارج أدلة النظام القياسية. ويشمل ذلك أي شيء موجود ضمن /usr/local/bin أو /opt، أو ضمن مدير إصدارات لغة، أو بيئة Python افتراضية، أو مساحة عمل Go. تفشل المهمة في سطرها الأول، وتكتب الصدفة خطأً بصيغة "not found"، وتختلف الصياغة الدقيقة حسب الصدفة التي شغّلت الأمر.

اعثر على المسار الفعلي لكل أمر تستخدمه مهمتك.

command -v docker
command -v node
readlink -f "$(command -v node)"

بعد ذلك، اكتب هذه المسارات المطلقة في المهمة، أو عيّن PATH مرة واحدة في أعلى ملف crontab.

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
0 3 * * * /usr/local/bin/mytool run

استخرج هذه القائمة من جهازك باستخدام echo "$PATH"، واحذف أي عنصر لا يوجد إلا داخل جلسة تفاعلية. تنطبق هنا قاعدة مهمة: لا يوسّع cron المتغيرات في أسطر التعيين هذه. يخزّن PATH=$PATH:/usr/local/bin النص الحرفي $PATH:/usr/local/bin، فتجد المهمة نفسها مع مسار بحث لا يحتوي على أي دليل صالح للاستخدام. اكتب القائمة كاملة.

يحتاج مدير الإصدارات إلى أكثر من مجرد مسار. يثبّت nvm وpyenv وrbenv وasdf دالة للصدفة أو دليلاً للـshims انطلاقاً من .bashrc، ولا يقرأ cron هذا الملف مطلقاً. استدعِ الملف التنفيذي ذي الإصدار باستخدام مساره المطلق، أو استورد ملف التهيئة الخاص بمدير الإصدارات في السطر الأول من برنامجك النصي.

السبب 2: تنهي علامة النسبة المئوية الأمر

في حقل الأمر في crontab، لا تُعد % حرفاً عادياً. تنهي أول % غير مسبوقة بشرطة مائلة عكسية الأمر. يمرر cron كل ما بعدها إلى الأمر كإدخال قياسي، وتتحول كل % لاحقة إلى سطر جديد. هذه ميزة فعلية في cron لتمرير إدخال قصير إلى برنامج، وهي أيضاً سبب كون اسم الملف الذي يتضمن التاريخ المثال الكلاسيكي على إدخال crontab معطّل.

اكتب 0 3 * * * /usr/bin/tar -czf /srv/backups/site-$(date +%F).tar.gz /srv/site، ولن يرى tar تاريخاً منسقاً. يقتطع cron السطر عند أول %، لذلك تتلقى الصدفة استبدال أمر غير مكتمل، بينما يصل باقي السطر كإدخال قياسي. اهرب من كل علامة نسبة مئوية باستخدام شرطة مائلة عكسية.

0 3 * * * /usr/bin/tar -czf /srv/backups/site-$(date +\%F).tar.gz /srv/site

تقرأ طبقتان هذا السطر الواحد بالترتيب. \% قاعدة cron يطبّقها cron قبل أن يبدأ أي شيء. $(date +\%F) هو استبدال الأوامر، وتطبّقه الصدفة التي يبدأها cron لاحقاً. معرفة الطبقة المسؤولة عن كل حرف هي الفكرة الأساسية.

الطريقة الأكثر أماناً هي إبقاء المنطق خارج crontab بالكامل. ضعه في برنامج نصي، حيث لا تحمل علامة النسبة المئوية أي معنى خاص.

#!/bin/bash
set -euo pipefail
stamp="$(date +%F)"
tar -czf "/srv/backups/site-${stamp}.tar.gz" /srv/site

يحتوي سطر crontab عندئذٍ على مسار وإعادة توجيه فقط. إن crontab الذي يمكنك قراءته بسرعة هو crontab الذي يمكنك تصحيح أخطائه.

السبب 3: أي crontab عدّلت؟

لا يوجد crontab واحد فقط. توجد عدة ملفات، بمالكين مختلفين وعدد حقول مختلف، وتصبح المهمة المكتوبة في الملف الخطأ غير مرئية.

  • يحرّر crontab -e ملف crontab للمستخدم الذي يشغّل الأمر. ويحرّر sudo crontab -e ملف root. وغالباً ما ينتهي شخصان يحاولان تصحيح المشكلة على الخادم نفسه إلى قراءة ملفين مختلفين.
  • يعرض sudo crontab -l -u deploy ملف crontab لمستخدم آخر. هذه هي طريقة التأكد مما هو مثبّت فعلياً للحساب الذي يُفترض أن يشغّل المهمة.
  • يحتوي /etc/crontab وكل ملف في /etc/cron.d على حقل إضافي بين الجدول الزمني والأمر: المستخدم الذي ستُشغَّل المهمة باسمه. إذا لصقت سطراً من crontab مستخدم، مكوّناً من خمسة حقول، في /etc/cron.d، فسيُقرأ أول جزء من أمرك على أنه اسم مستخدم.
  • يجب تسمية الملفات في /etc/cron.d باستخدام الأحرف والأرقام والشرطات السفلية والواصلات فقط. يُتخطّى الملف الذي اسمه backup.sh أو site.conf بسبب اسمه وحده. أعد تسميته إلى backup وافحص السجل مرة أخرى.
  • يجب أن تكون ملكية الملفات في /etc/cron.d للمستخدم root، وألا تكون قابلة للكتابة من المجموعة أو المستخدمين الآخرين. يعرض لك ls -l /etc/cron.d الأمرين معاً.
  • تتبع البرامج النصية الموضوعة في /etc/cron.daily والأدلة المشابهة له قاعدة التسمية نفسها، ويجب أن تحمل أيضاً بت التنفيذ. يؤدي غياب بت التنفيذ إلى تخطيها بصمت.
  • يحدّد /etc/cron.allow و/etc/cron.deny من يُسمح له بتثبيت crontab أصلاً. إذا كان أحدهما موجوداً على خادمك، فاقرأه قبل افتراض أن مستخدمك مسموح له بذلك.

ثبّت crontab لمستخدم باستخدام الأمر crontab بدلاً من تعديل ملف spool يدوياً، لأن crontab يحلل الملف قبل تثبيته. عند الحفظ، اقرأ النص الذي يعرضه الأمر. إذا رفض الملف، تظل النسخة السابقة قيد التشغيل ولا يدخل تغييرك حيّز التنفيذ، وهذا يبدو تماماً كأن cron يتجاهلك.

يحدّد المالك أيضاً الصلاحيات. تنشئ المهمة الموجودة في crontab الخاص بـroot ملفات يملكها root، وقد لا يتمكن التطبيق الذي يقرأها من الكتابة إليها. ولا تستطيع مهمة في crontab لمستخدم عادي قراءة دليل لا يملك root وحده صلاحية الوصول إليه. طابق المالك مع طبيعة العمل: صيانة التطبيق تخص حساب التطبيق نفسه، وهذا هو سبب استبدال wp-cron في WordPress بمهمة cron للنظام. يأتي نمط الملفات التي تنشئها مهمتك من umask الذي ترثه، وهذه قيمة أخرى لا تكون بالضرورة قيمة shell، لذلك يجدر بك قراءة كيفية تحديد umask لصلاحيات الملفات إذا كان ناتج المهمة يُنشأ من دون إمكانية قراءته.

السبب 4: خرج التنفيذ أُرسل إلى بريد لا يقرأه أحد

يجمع cron كل ما تكتبه المهمة إلى الخرج القياسي والخطأ القياسي. إذا كتبت المهمة أي محتوى، يسلّم cron هذا النص إلى نظام البريد المحلي، ويوجّهه إلى مالك crontab أو إلى العنوان الذي يحدده MAILTO. في VPS محدود عادةً لا يكون هناك MTA (وكيل نقل البريد) مثبت، لذلك لا يسلّم أي مكوّن الرسالة. كان الخطأ موجوداً للحظة، ثم اختفى دون وجهة. هذا هو السبب الكامل وراء ظهور المهمة المعطلة وكأنها صامتة.

وجّه الخرج إلى ملف تتحكم فيه بدلاً من ذلك.

0 3 * * * /usr/local/sbin/backup-site.sh >> /var/log/backup-site.log 2>&1

يضيف >> الخرج القياسي إلى الملف. ويوجّه 2>&1 الخطأ القياسي إلى الوجهة التي يشير إليها الخرج القياسي حالياً، لذلك يجب أن يأتي بعد إعادة التوجيه. إذا كُتبت بالطريقة الأخرى، كـ 2>&1 >> file، يحتفظ الخطأ القياسي بوجهته الأصلية، والخطأ الذي تبحث عنه هو بالضبط الجزء الذي لا يصل إلى الملف.

السجل journal هو وجهة جيدة أخرى. يكتب logger في syslog باستخدام وسم تختاره.

0 3 * * * /usr/local/sbin/backup-site.sh 2>&1 | logger -t backup-site

اقرأه مجدداً باستخدام journalctl -t backup-site. يحافظ هذا على خرج المهمة بجوار إدخالات cron، مما يجعل تتبع التسلسل الزمني سهلاً. إذا كنت تحتاج أيضاً إلى سجل يوضح أي شخص نفّذ أي أمر على الخادم، فهذا نظام منفصل، ويغطيه تدقيق أوامر المستخدمين على خادمك.

يوقف MAILTO="" في أعلى crontab إرسال البريد للمهام التي تليه. لا يفيد ضبط MAILTO على عنوان حقيقي إلا إذا كان هناك MTA يعمل، لذلك تحقّق أولاً من مغادرة البريد للخادم قبل الاعتماد عليه.

قاعدة واحدة أثناء تصحيح الأخطاء: لا تضف > /dev/null 2>&1 أبداً. فهذا هو السطر الأكثر شيوعاً في كل crontab، ويتخلص من الدليل الوحيد المتاح لديك. أعده لاحقاً إذا أردت، بعد أن تعمل المهمة.

السبب 5: يفترض البرنامج النصي وجود بيئة لا يوفرها cron

بعد العثور على الأمر والتقاط مخرجاته، تبقى كل القيم الأخرى التي تمنحك إياها جلستك تلقائياً.

  • قد لا تكون shell هي bash. تحقّق باستخدام ls -l /bin/sh. في Debian وUbuntu، يشير ذلك إلى dash، ولذلك يفشل اختبار القوسين المزدوجين والمصفوفات وsource بسبب خطأ في الصياغة. أضف سطر #!/bin/bash إلى البرنامج النصي واستدعِ البرنامج النصي، أو عيّن SHELL في بداية crontab.
  • لا يكون مجلد العمل هو المجلد الذي كنت موجوداً فيه. استخدم المسارات المطلقة في كل مكان، أو استخدم cd للانتقال إلى المجلد في السطر الأول من البرنامج النصي. المسار النسبي هو السبب الفردي الأكثر شيوعاً في أن مهمة ما «تعمل عند تشغيلها يدوياً».
  • لا تكون locale هي locale الخاصة بجلستك. يمكن لأي أمر ينسّق تاريخاً أو رقماً أو يفرز نصاً أن ينتج مخرجات مختلفة تحت LANG مختلفة. إذا كانت خطوة لاحقة تحلل تلك المخرجات، فعيّن locale في البرنامج النصي بدلاً من افتراض ثباتها.
  • لا توجد TTY (طرفية). قد يتوقف الأمر الذي يطلب تأكيداً أو يفتح محرراً أو يعرض شريط تقدم، أو قد يخرج. أضف أي خيار non-interactive يوفره البرنامج.
  • لا يوجد SSH agent. لا تكون SSH_AUTH_SOCK موجودة في بيئة cron، ولذلك يفشل أمر ssh أو rsync في المصادقة إذا كان قد نجح سابقاً لأن agent كان محمّلاً. امنح المهمة مفتاحاً خاصاً بها، ويجب أن يكون مملوكاً لمستخدم المهمة.
  • لا توجد user session bus، ولذلك يفشل systemctl --user من مهمة cron إلى أن يتم تعيين XDG_RUNTIME_DIR. تكون system unit حلاً أفضل.

في Fedora وRocky وAlma يوجد سبب محتمل إضافي. يفرض SELinux قيوداً على مهام cron، ولذلك تُرفض المهمة عند الوصول إلى مسار يحمل label غير متوقعة، حتى عندما تبدو أذونات الملف صحيحة. تحقّق من حالات الرفض باستخدام sudo ausearch -m avc -ts recent، واقرأ أساسيات SELinux للخادم قبل تعطيل أي شيء.

المسبار الذي يستغرق دقيقة واحدة ويعرض بيئة cron

توقّف عن تخمين محتويات بيئة cron واقرأها مباشرة. اكتب برنامجاً نصياً يفرغ كل شيء، وجدوله للتشغيل كل دقيقة، وانتظر، ثم اقرأ الملف.

cat > /home/deploy/cron-probe.sh <<'EOF'
#!/bin/bash
echo "=== probe ==="
date -Is
pwd
id
echo "SHELL=$SHELL"
echo "LANG=$LANG"
command -v node || echo "node is not on this PATH"
env | sort
EOF
chmod +x /home/deploy/cron-probe.sh

أضف سطراً واحداً إلى crontab الخاص بالمستخدم الذي تُشغَّل الحسابات الفعلية باسمه، مع استخدام مسارات مطلقة على جانبي السطر.

* * * * * /home/deploy/cron-probe.sh >> /home/deploy/cron-probe.log 2>&1

انتظر دقيقة واحدة، ثم اقرأ /home/deploy/cron-probe.log وقارنه بالأوامر نفسها عند تشغيلها في shell الخاص بك. يفسّر سطر PATH، ودليل العمل، والإعدادات المحلية سبب الفشل غالباً بمفردها. لاحظ تفصيلين في الإعداد: توجد علامات النسبة المئوية داخل البرنامج النصي، حيث لا تنطبق قاعدة cron عليها، ومسار السجل قابل للكتابة من قِبل مستخدم المهمة.

احذف سطر crontab فور حصولك على الإجابة. فالمهمة التي تعمل كل دقيقة وتضيف إلى ملف ستملأ القرص الصغير، وستفعل ذلك بصمت.

هل الجدولة هي التي قصدتها؟

يبدأ سطر crontab الخاص بالمستخدم بخمسة حقول: الدقيقة، والساعة، ويوم الشهر، والشهر، ويوم الأسبوع. يتفاعل حقلان منها بطريقة تفاجئ بعض المستخدمين.

عندما يكون كل من يوم الشهر ويوم الأسبوع مقيّداً، أي لا يساوي أيٌّ منهما *، يشغّل cron المهمة عندما يطابق أيٌّ من الحقلين. لا تعني 0 0 13 * 5 «الجمعة 13». بل تشغّل المهمة عند منتصف الليل في اليوم 13 من كل شهر، وعند منتصف الليل كل يوم جمعة. للحصول على يوم محدد واحد، اترك أحد الحقلين يساوي *، واختبر الحقل الآخر داخل البرنامج النصي.

يستخدم cron المنطقة الزمنية للنظام. تأتي كثير من صور VPS مضبوطة على UTC (التوقيت العالمي المنسق)، لذلك تعمل المهمة التي جدولتَها عند 03:00 في الساعة 03:00 بتوقيت UTC، وقد يكون ذلك في منتصف فترة بعد الظهر لديك. يطبع timedatectl المنطقة الزمنية التي يستخدمها خادمك فعلياً. اعرض ناتجه بدلاً من افتراض أنها تطابق المنطقة الزمنية في حاسوبك المحمول.

هناك مشكلتان إضافيتان في الجدولة تجدر معرفتهما. يُشغَّل @reboot عندما يبدأ cron نفسه، وهذا لا يحدث بالضرورة في الوقت الذي تصبح فيه الشبكة جاهزة. لذلك قد تفشل مهمة تحتاج إلى DNS أو إلى مضيف بعيد أثناء الإقلاع، ثم تنجح في كل تشغيل يدوي لاحق. كذلك، لا يمنع شيء مهمة بطيئة من البدء مجدداً بينما لا تزال النسخة السابقة قيد التشغيل. ضعها داخل قفل.

*/5 * * * * /usr/bin/flock -n /tmp/backup-site.lock /usr/local/sbin/backup-site.sh >> /var/log/backup-site.log 2>&1

يتوقف flock -n فوراً عندما يكون القفل مستخدماً، لذلك يتوقف التشغيل المتداخل بدلاً من أن يتراكم فوق التشغيل الأول.

عندما يكون مؤقت systemd هو الأداة الأنسب

يؤدي cron مهمة واحدة جيداً: تشغيل هذا الأمر في هذا الوقت. لكنه ضعيف في كل ما عدا ذلك. يوفّر المؤقت السجل journal من دون أي إعادة توجيه، وحالة خروج يمكنك الاستعلام عنها لاحقاً، وترتيباً بالنسبة إلى network-online.target، وتأخيراً عشوائياً حتى لا تبدأ مئة خادم في الثانية نفسها. عندما تحتاج مهمتك إلى أي من ذلك، فإن خدمة ومؤقت systemd على VPS يتطلبان جهداً أقل من تبرير سطر في crontab. يطرح عليك جزء كتابة الخدمة سؤالاً لا يطرحه cron أبداً، وهو كيف تعرف الوحدة أن العمل بدأ فعلياً. لذلك اقرأ أولاً ما الذي يعنيه Type= لوحدات simple وforking وnotify، لأن النص البرمجي الذي يحوّل نفسه إلى daemon عند استخدام النوع الافتراضي يترك الوحدة في حالة active من دون عملية تعمل خلفها. وينطبق الأمر نفسه على سلوك إعادة المحاولة، لأن سياسات إعادة تشغيل systemd تحدد ما يحدث بعد الفشل، بينما لا يملك cron إجابة عن هذا السؤال إطلاقاً.

أبقِ cron للمهام الصغيرة. انقل كل ما لديه تبعيات أو سياسة لإعادة المحاولة إلى مؤقت. يمكن لكليهما العمل على الخادم نفسه، لذلك لا يلزمك إكمال عملية النقل في جلسة واحدة.

FAQ

لماذا تعمل مهمة cron يدوياً لكنها تفشل عند تشغيلها من cron؟

لأن بيئة shell تختلف عن بيئة cron. يقرأ shell الخاص بتسجيل الدخول /etc/profile و~/.bashrc، وهما يضبطان PATH والـlocale ومتغيرات agent الخاصة بك. يبدأ cron الأمر من دون أي من ذلك، ومن دليل عمل مختلف، وأحياناً باستخدام shell مختلف. استخدم المسارات المطلقة لكل أمر، واضبط ما تحتاج إليه في أعلى crontab أو داخل البرنامج النصي، وجدول مهمة اختبار لمدة دقيقة واحدة تشغّل env | sort وpwd وid في ملف سجل، حتى تتمكن من قراءة بيئة cron الفعلية بدلاً من التخمين.

كيف أتحقق من أن cron شغّل مهمتي فعلاً؟

اقرأ سجل daemon. استخدم journalctl -u cron في Debian وUbuntu، أو journalctl -u crond في Fedora وRocky وAlma؛ وتنقل بعض الصور الرسائل عبر rsyslog إلى ملف ضمن /var/log بدلاً من ذلك. ابحث عن إدخال في الدقيقة التي يحددها الجدول، وتحقق من أنه يذكر أمرك. يعني غياب الإدخال أن cron لم يحمّل الجدول، لذا تأكد من أنك عدّلت crontab الصحيح. ويعني وجود إدخال من دون نتيجة أن الأمر بدأ ثم توقف، لذا التقط مخرجاته باستخدام إعادة التوجيه.

لماذا يتسبب date +%Y في حدوث خطأ داخل crontab؟

يتعامل cron مع % على أنه محرف خاص في حقل الأمر. ينهي أول % غير محمي الأمر، ويمرر كل ما بعده إلى ذلك الأمر على أنه الإدخال القياسي، ويحوّل كل % لاحق إلى سطر جديد. لذلك لا يصل اسم الملف المنسق بالتاريخ إلى البرنامج الذي كتبته من أجله. احمِ كل علامة مئوية باستخدام \%، أو انقل الأمر إلى برنامج نصي واستدعِ البرنامج النصي من cron، لأن علامة المئوية لا تحمل معنى خاصاً داخل البرنامج النصي.

إلى أين تذهب مخرجات مهمة cron؟

تذهب إلى نظام البريد المحلي، وتُوجَّه إلى مالك crontab أو إلى أي جهة يحددها MAILTO. لا تحتوي معظم صور VPS على وكيل نقل بريد مثبت، لذلك تُهمل الرسالة وتبدو المهمة صامتة. أعد توجيه المخرجات إلى ملف باستخدام >> /path/to/log 2>&1، مع الحفاظ على هذا الترتيب حتى يتبع الخطأ القياسي المخرجات القياسية، أو مررها عبر logger -t myjob واقرأها مجدداً باستخدام journalctl -t myjob. لا تستخدم > /dev/null 2>&1 ما دمت لا تزال في مرحلة تصحيح الأخطاء.

هل أستخدم cron أم مؤقت systemd؟

استخدم cron لأمر بسيط في وقت محدد، وخصوصاً إذا كنت قد تحتاج إلى نقله إلى جهاز لا يشغّل systemd. استخدم المؤقت عندما تريد حفظ المخرجات في journal من دون إعادة توجيه، أو الحصول على حالة خروج يمكن الاستعلام عنها، أو ترتيب التشغيل بعد جاهزية الشبكة، أو إضافة تأخير عشوائي قبل البدء، أو تطبيق سياسة لإعادة المحاولة بعد الفشل. يمكن لكليهما العمل على الخادم نفسه، لذا يمكنك نقل المهام واحدة تلو الأخرى عندما يصبح ذلك مناسباً.