۱۳. زمانبندی کارها¶
کار زمانبندیشده بیصدا شکست میخورد: کسی نگاهش نمیکند تا یک روز بفهمند سه ماه است بکاپ نگرفته. پس هر کار زمانبندیشده سه چیز لازم دارد: لاگ، قفل ضد همپوشانی و سیگنال موفقیت.
راهنمای سریع¶
| فرمان | کاربرد | ریسک |
|---|---|---|
crontab -l / ls /etc/cron.d |
مشاهدهٔ cron | بدون تغییر |
systemctl list-timers --all |
فهرست timerها | بدون تغییر |
systemd-analyze calendar '...' |
آزمون عبارت زمانی | بدون تغییر |
crontab -e / at |
افزودن کار | تغییر |
crontab -r |
حذف همهٔ cron های کاربر، بدون تأیید | مخرب |
cron¶
crontab -l
crontab -e
sudo crontab -l
sudo crontab -l -u appuser
ls -lah /etc/cron.d/ /etc/cron.daily/
for u in $(cut -d: -f1 /etc/passwd); do sudo crontab -l -u "$u" 2>/dev/null | sed "s/^/$u: /"; done # همهٔ کاربران
نمونه اجرای روزانه در ساعت 02:15 با قفل و لاگ:
# قالب: دقیقه ساعت روز-ماه ماه روز-هفته فرمان
MAILTO=""
15 2 * * * flock -n /var/lock/backup.lock /usr/local/sbin/backup.sh >> /var/log/backup.log 2>&1
| عبارت | معنی |
|---|---|
*/5 * * * * |
هر ۵ دقیقه |
0 */6 * * * |
هر ۶ ساعت، دقیقهٔ ۰ |
30 1 * * 1-5 |
۰۱:۳۰ دوشنبه تا جمعه (۱=دوشنبه … ۵=جمعه) |
0 3 1 * * |
روز اول هر ماه ۰۳:۰۰ |
@reboot |
بعد از هر بوت |
- قالب: دقیقه، ساعت، روز ماه، ماه، روز هفته.
- محیط cron محدود است (
PATHحداقلی، بدون ترمینال)؛ مسیر کامل فرمانها و متغیرهای محیطی لازم را صریح بنویسید. - خروجی و خطاها را ثبت کنید (
>> log 2>&1) و اسکریپت را با همان کاربر و محیط تمیز آزمایش کنید:env -i /bin/sh -c '/usr/local/sbin/backup.sh'. flock -nاز اجرای همزمان دو نمونه (وقتی اجرای قبلی هنوز تمام نشده) جلوگیری میکند.
دامهای cron که همه یک بار میخورند
- علامت
%در خط cron یعنی «خط جدید»؛ باید\%نوشته شود (مثلاًdate +\%F). crontab -rبدون تأیید همهٔ cron ها را پاک میکند و کنار-eروی کیبورد است. ازcrontab -riاستفاده کنید یا قبلشcrontab -l > backup.- اگر هم «روز ماه» و هم «روز هفته» را مقید کنید، شرایط OR میشوند، نه AND (
0 0 13 * 5= روز ۱۳ یا هر جمعه). - در
/etc/cron.d/هر خط ستون کاربر دارد (15 2 * * * root /path) و فایل باید مالک root و بدون دسترسی نوشتن گروه باشد. - فایلهای داخل
/etc/cron.dailyوcron.dبا نام دارای نقطه (backup.sh) در برخی توزیعها نادیده گرفته میشوند (run-parts)؛ بدون پسوند و با اجرایی بودن بسازید. - cron با منطقهٔ زمانی سیستم و بدون جبران DST کار میکند؛ کار ساعت ۰۲:۳۰ در روز تغییر ساعت ممکن است دوبار یا هیچبار اجرا شود. ترجیحاً سیستم روی UTC.
عیبیابی cron:
journalctl -u cron --since today # RHEL: -u crond
grep CRON /var/log/syslog | tail # Debian بدون journal
# دیدن محیط واقعی cron (موقت!): * * * * * env > /tmp/cronenv — بعد از دیدن حذف کنید
systemd timer¶
برای سرویسهای جدید، timer نسبت به cron امکاناتی مانند وابستگی سرویس، ثبت در journal، محدودیت منابع، اجرای عقبافتاده و تأخیر تصادفی را سادهتر میکند.
# /etc/systemd/system/backup.service (نمونه)
[Unit]
Description=Nightly backup
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/backup.sh
User=root
Nice=10
# /etc/systemd/system/backup.timer (نمونه)
[Unit]
Description=Nightly backup timer
[Timer]
OnCalendar=*-*-* 02:15:00
Persistent=true # اگر سرور خاموش بود، بعد از بوت جبران کن
RandomizedDelaySec=300 # پخش بار روی چند سرور
Unit=backup.service
[Install]
WantedBy=timers.target
systemd-analyze calendar '*-*-* 02:15:00' # نمایش زمان بعدی اجرا
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers --all | grep backup
sudo systemctl start backup.service # اجرای دستی برای تست
journalctl -u backup.service --since today
systemctl status backup.service --no-pager # exit code آخرین اجرا
at¶
پس از اجرای at 23:00 فرمانها را وارد و با Ctrl+D ثبت کنید. دسترسی به at ممکن است با سیاست سیستم (/etc/at.allow/at.deny) محدود شده باشد. at برای «برگرداننده»های موقت (rollback زماندار) بسیار مفید است (فایروال).
بررسی زمان¶
تنظیم timezone را با نیاز برنامهها هماهنگ کنید. در سامانههای توزیعشده، UTC برای لاگها معمولاً سادهتر است؛ timezone نمایشی را مستند کنید. ساعت اشتباه = cron/گواهی/Kerberos/لاگ همه خراب.
خطاهای رایج¶
| نشانه | علت احتمالی | روش بررسی |
|---|---|---|
| دستی کار میکند، در cron نه | PATH/محیط/مسیر نسبی | مسیر کامل؛ env -i ؛ لاگ با 2>&1 |
| cron اجرا شد ولی خروجی نیست | ایمیل محلی (MAILTO) | >> log 2>&1 ؛ MAILTO="" |
| کار دوبار همزمان اجرا میشود | اجرای قبلی تمام نشده | flock -n |
فایل در cron.daily اجرا نمیشود |
نام با نقطه/غیر اجرایی | run-parts --test /etc/cron.daily |
date +%F در cron خراب |
% escape نشده |
\% |
| timer هرگز اجرا نمیشود | enable نشده/عبارت اشتباه |
list-timers ، systemd-analyze calendar |
| timer اجرا شد ولی کار شکست خورد | خطا در service | systemctl status X.service ، journalctl -u X.service |
نکات امنیتی و عملیاتی¶
- cron/timer فایلهای اسکریپت را باید فقط root بتواند تغییر دهد؛ اسکریپتی که root اجرا میکند ولی دیگران مینویسند = ارتقای دسترسی.
- هر کار حیاتی «نبود موفقیت» را هشدار بدهد (heartbeat)؛ نه فقط خطا.
- cron ها را در مخزن Git نگه دارید و دورهای با سرور مقایسه کنید.
خلاصهٔ اجرایی¶
- مسیر کامل،
flock، لاگ،\%. crontab -rرا فراموش کنید؛-ri.- کار جدید → systemd timer با
Persistent=true. - آزمون با
env -iوsystemd-analyze calendar.