يستحق الخادم ثمنه حين يعمل وأنت نائم: نسخ احتياطية، وتدوير السجلات، وتجديد الشهادات، وتقرير في التاسعة. في Linux مُجدولان لهذا. cron عمره أربعون عامًا ويكفيه سطر واحد. مؤقتات systemd تحتاج ملفين صغيرين، وتعطي في المقابل سجلات وتعويضًا لما فات بعد التوقف وتوقيتًا دقيقًا. يشرح هذا الدليل الاثنين على Ubuntu 24.04، وكل سلوك فيه جرى التحقق منه على خادم جديد من صورتنا، بما في ذلك الأخطاء الثلاثة التي تجعل مهمة cron تفشل دون أي كلمة.
تحتاج إلى مستخدم بصلاحية sudo؛ دليل إعداد Ubuntu ينشئ واحدًا.
1. cron في خمس دقائق
cron مثبّت ويعمل على صور Ubuntu وDebian لدينا. لكل مستخدم جدول مهام؛ عدّل جدولك بالأمر:
crontab -e
كل سطر هو خمسة حقول زمنية وأمر:
# min hour day month weekday command
30 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
*/5 * * * * /usr/local/bin/check.sh
0 9 * * 1-5 /usr/local/bin/report.sh
@reboot /usr/local/bin/start-tunnel.sh
أي: في 03:30 كل ليلة، وكل 5 دقائق، وفي 09:00 أيام العمل، ومرة واحدة بعد كل إقلاع. */5 تعني كل قيمة خامسة، و1-5 نطاقًا، و1,15 قائمة. تُطبَّق المنطقة الزمنية للخادم، وهي UTC في صورنا؛ اضبط منطقتك مرة واحدة عبر دليل اسم المضيف والمنطقة الزمنية وسيتبعها cron.
تحقق مما جرى تشغيله بـ journalctl -u cron. كل تشغيل يسجّل المستخدم والأمر، وهناك تظهر الفخاخ الثلاثة.
الفخ 1: الناتج يختفي. يرسل cron ناتج المهمة إلى المستخدم بالبريد. لا يوجد خادم بريد في صورتنا، لذا ظهر في السجل (CRON) info (No MTA installed, discarding output) وضاع الناتج. أعِد توجيهه بنفسك كما في المثال الأول بـ >> /var/log/backup.log 2>&1.
الفخ 2: علامة النسبة المئوية. في crontab تُنهي % الأمر وتحوّل ما بعدها إلى إدخال قياسي. قمنا بجدولة date +%F > /tmp/today. يُظهر السجل ما شغّله cron فعلًا: CMD (date +). لم يُكتب أي ملف ولم يصلنا أي خطأ. اكتب \%، أو ضع الأمر في سكربت وجدول السكربت.
الفخ 3: بيئة مختلفة. يشغّل cron المهام بـ /bin/sh لا بـ bash، في مجلدك المنزلي وببيئة محدودة. على Ubuntu 24.04 كان PATH أفضل من سمعته: المسار الكامل للنظام بما فيه /usr/local/bin و/snap/bin، لـ root وللمستخدم العادي. ما زال ينقصه كل ما في مجلدك المنزلي: ~/.local/bin وnode من nvm وpipx وcargo. استخدم المسارات الكاملة في المهمة أو ابدأ السطر بـ . $HOME/.profile;.
المهام التي تخص النظام لا المستخدم توضع في /etc/cron.d/ كملف فيه حقل إضافي هو المستخدم:
30 3 * * * root /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
يشغّل Ubuntu أيضًا كل ما في /etc/cron.hourly وcron.daily وcron.weekly وcron.monthly، في الدقيقة 17 من كل ساعة، وفي 06:25، وفي 06:47 يوم الأحد، وفي 06:52 أول كل شهر. ضع هناك سكربتًا قابلًا للتنفيذ وسيعمل مع البقية.
2. مؤقتات systemd
المؤقت وحدتان: خدمة تؤدي العمل ومؤقت يحدد متى. أنشئ السكربت أولًا ثم الوحدتين.
sudo nano /usr/local/bin/backup.sh
sudo chmod +x /usr/local/bin/backup.sh
sudo nano /etc/systemd/system/backup.service
[Unit]
Description=Nightly backup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
sudo nano /etc/systemd/system/backup.timer
[Unit]
Description=Run the backup every night at 03:30
[Timer]
OnCalendar=*-*-* 03:30
Persistent=true
AccuracySec=1m
[Install]
WantedBy=timers.target
فعّل المؤقت لا الخدمة:
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers backup.timer
يعرض list-timers التشغيل التالي والوقت المتبقي حتى حلوله والتشغيل الأخير. السجلات لا تحتاج إلى إعداد: يحتوي journalctl -u backup.service على كل بدء وكل انتهاء وكل سطر ناتج مع الوقت. لتشغيل المهمة فورًا استخدم sudo systemctl start backup.service؛ وبهذا أيضًا تختبر السكربت قبل أن تثق بالجدول.
صيغة التقويم. تُقرأ OnCalendar هكذا: يوم-الأسبوع سنة-شهر-يوم ساعة:دقيقة:ثانية، و* لأي قيمة. اختبر التعبير قبل استخدامه:
systemd-analyze calendar "Mon..Fri *-*-* 03:00" --iterations 2
يطبع الصيغة الموحّدة والتواريخ التالية. بعض التعبيرات التي تحققنا منها:
| OnCalendar | المعنى |
|---|---|
*-*-* 03:30 | كل يوم في 03:30 |
Mon..Fri *-*-* 09:00 | أيام العمل في 09:00 |
*:0/15 | كل 15 دقيقة |
weekly | الاثنين في 00:00 |
*-*-01 04:00 | أول كل شهر في 04:00 |
*-*-* 03:00 Europe/Kyiv | 03:00 بتوقيت كييف؛ عمل في 01:00 UTC في اختبارنا |
ثلاثة إعدادات تستحق المعرفة. يحفظ Persistent=true التشغيل الأخير على القرص ويعوّض تشغيلًا فات أثناء إطفاء الخادم أو إيقاف المؤقت. أوقفنا مؤقتنا الذي يعمل كل دقيقتين، وانتظرنا حتى مرّ تشغيل مجدول، ثم أعدنا تشغيله: انطلق التشغيل الفائت في الثانية نفسها. دون Persistent ينتظر المؤقت الموعد التالي فحسب.
AccuracySec هو المفاجأة. يجمع systemd المؤقتات افتراضيًا في نافذة مدتها دقيقة لتقليل إيقاظ النظام، لذا جاء تشغيلنا الأول في 07:42:18 لا 07:42:00. ومع AccuracySec=1s وقعت التشغيلات التالية على الثانية تمامًا في 07:46:00 و07:48:00. اضبطه حين تهمّ الدقيقة؛ واترك القيمة الافتراضية لنسخة احتياطية ليلية.
RandomizedDelaySec=10m يفعل العكس عمدًا: يوزّع البدء على نافذة حتى لا تضرب عشرة خوادم مخزن النسخ الاحتياطية نفسه في الثانية نفسها.
لمهمة تُنفَّذ مرة واحدة لا تحتاج إلى أي ملف:
sudo systemd-run --on-active=30m --unit=cleanup-once /usr/local/bin/cleanup.sh
ينشئ هذا مؤقتًا عابرًا يعمل مرة واحدة ثم يختفي؛ وحتى ذلك الحين يعرضه systemctl list-timers.
3. أيهما تستخدم
| cron | مؤقت systemd | |
|---|---|---|
| الإعداد | سطر واحد | ملفان |
| السجلات | فقط إن أعدت توجيه الناتج | journalctl -u name.service |
| تشغيل فائت أثناء إطفاء الخادم | يضيع | يعمل عند الإقلاع مع Persistent=true |
| المهمة ما زالت تعمل عند الموعد التالي | تبدأ نسخة ثانية | يُتخطّى حتى تنتهي الأولى |
| التوقيت الدقيق | حتى الدقيقة | حتى الثانية مع AccuracySec=1s |
| الحالة | لا شيء | list-timers وsystemctl status |
استخدم cron لسطر سريع ستعرفه بعد عام. واستخدم المؤقت لكل ما تحتاج إلى رؤية فشله، أو لا يجوز أن يتداخل، أو يجب أن يعمل بعد إعادة تشغيل فاتته: النسخ الاحتياطية، وتجديد الشهادات، وتنظيف قواعد البيانات. إذا كان من الممكن أن تتداخل مهمة cron فغلّفها: flock -n /tmp/backup.lock /usr/local/bin/backup.sh، وستخرج النسخة الثانية فورًا.
كلا المُجدولين يشغّل مهمة ثم يتوقف. أما البرنامج الذي يجب أن يعمل طوال الوقت ويعود بعد التعطل فيحتاج إلى خدمة لا إلى جدول؛ راجع كيف تنشئ خدمة systemd، ولـ Windows راجع كيف تشغّل سكربتًا 24/7 على Windows Server. مؤقت أول جيد هو الذي في دليل النسخ الاحتياطي باستخدام restic؛ والتحديثات الأمنية التلقائية مؤقت يأتي مع Ubuntu أصلًا، وهو apt-daily-upgrade.timer، واحد من 17 مؤقتًا تعمل على خادم جديد.
التعليقات
لا تعليقات بعد. كن الأول.