آموزش سرور

آموزش Cron در لینوکس؛ زمان‌بندی خودکار بکاپ، اسکریپت و پاک‌سازی

تهیه: کلودیفای (نگارش با کمک هوش مصنوعی) · انتشار: · زمان مطالعه: ۸ دقیقه

root@server: ~$ crontab -lSHELL=/bin/bash30 3 * * * /usr/local/bin/backup-db.sh >$ grep CRON /var/log/syslog | tail -n 2... CRON[...]: (root) CMD (/usr/local/bi$ timedatectl | grep zoneCronآموزش سرورآموزش Cron در لینوکس؛زمان‌بندی خودکار بکاپ،اسکریپت و پاک‌سازیمجلهٔ کلودیفایclodify.net/blog
پاسخ کوتاه

cron سرویس زمان‌بندی لینوکس است که دستورها را در زمان‌های مشخص اجرا می‌کند. با crontab -e فهرست کارهای کاربر را ویرایش کنید؛ هر خط پنج فیلد زمان (دقیقه، ساعت، روز ماه، ماه، روز هفته) و سپس دستور دارد. همیشه مسیر کامل فایل‌ها را بنویسید، خروجی را در فایل لاگ ذخیره کنید، منطقهٔ زمانی سرور را بدانید و برای کارهای طولانی با flock از اجرای هم‌زمان جلوگیری کنید.

cron چیست و چه کارهایی را خودکار می‌کند؟

بخش زیادی از نگهداری سرور کارهای تکراری است: گرفتن بکاپ شبانه از دیتابیس، پاک کردن فایل‌های موقت، تمدید گواهی، ارسال گزارش، اجرای یک اسکریپت پایتون هر پنج دقیقه یا ری‌استارت دوره‌ای یک سرویس. انجام دستی این کارها هم وقت‌گیر است و هم دیر یا زود فراموش می‌شود. cron سرویس استاندارد لینوکس برای همین کار است: در پس‌زمینه اجرا می‌شود، هر دقیقه فهرست کارهای زمان‌بندی‌شده را بررسی می‌کند و هر کاری که زمانش رسیده باشد را اجرا می‌کند.

cron روی تقریباً همهٔ توزیع‌های سرور (اوبونتو، دبیان، AlmaLinux و Rocky) از قبل نصب و فعال است. برای اطمینان:

systemctl status cron      # اوبونتو و دبیان
systemctl status crond     # AlmaLinux و Rocky
cron چطور کار می‌کند
خواندنزمان رسیدثبت خروجیcrontabفهرست کارها و زمان‌هاسرویس cronبررسی هر دقیقهاسکریپتبکاپ، پاک‌سازی، گزارشفایل لاگخروجی و خطاهاخواندنزمان رسیدثبت خروجیcrontabفهرست کارها و زمان‌هاسرویس cronبررسی هر دقیقهاسکریپتبکاپ، پاک‌سازی، گزارشفایل لاگخروجی و خطاها
شکل ۱ سرویس cron هر دقیقه crontabها را بررسی می‌کند و کارهایی را که زمانشان رسیده اجرا می‌کند؛ خروجی را خودتان باید به لاگ بفرستید.

ساختار یک خط crontab

هر کار زمان‌بندی‌شده یک خط است که از پنج فیلد زمان و سپس دستور تشکیل می‌شود:

┌───────── دقیقه (0-59)
│ ┌─────── ساعت (0-23)
│ │ ┌───── روز ماه (1-31)
│ │ │ ┌─── ماه (1-12)
│ │ │ │ ┌─ روز هفته (0-7، صفر و هفت = یکشنبه)
│ │ │ │ │
* * * * * دستور

نمادهای مهم:

نماد معنی مثال
* همهٔ مقادیر * در فیلد ساعت = هر ساعت
, فهرست مقادیر 1,15 = روز اول و پانزدهم
- بازه 1-5 در روز هفته = دوشنبه تا جمعه
/ گام */10 در دقیقه = هر ده دقیقه

به‌جای پنج فیلد، چند میان‌بر هم وجود دارد: @reboot (یک بار پس از هر بوت)، @hourly، @daily، @weekly و @monthly.

ویرایش crontab و مثال‌های کاربردی

هر کاربر crontab مخصوص خود را دارد. برای ویرایش:

crontab -e        # ویرایش crontab کاربر فعلی
crontab -l        # نمایش کارهای فعلی
sudo crontab -e   # crontab کاربر root

بار اول از شما می‌پرسد کدام ویرایشگر را می‌خواهید؛ nano برای شروع ساده‌تر است. چند مثال رایج:

# بکاپ دیتابیس هر شب ساعت ۳:۳۰
30 3 * * * /usr/local/bin/backup-db.sh >> /var/log/backup-db.log 2>&1

# اجرای اسکریپت پایتون هر ۵ دقیقه
*/5 * * * * /usr/bin/python3 /opt/bot/check.py >> /var/log/bot-check.log 2>&1

# پاک کردن فایل‌های موقت قدیمی‌تر از ۷ روز، هر یکشنبه
0 4 * * 0 find /var/tmp/myapp -type f -mtime +7 -delete

# اجرای یک اسکریپت پس از هر بوت
@reboot /opt/myapp/start.sh

توضیح >> file 2>&1: خروجی عادی و خطاها هر دو به انتهای فایل لاگ اضافه می‌شوند. بدون این بخش، خروجی کار یا گم می‌شود یا برای ارسال ایمیل محلی تلاش می‌شود که روی بیشتر سرورها پیکربندی نشده است.

برای ساختن یا بررسی عبارت زمان، می‌توانید هر بار جدول بالا را مرور کنید؛ اما بهترین تمرین این است که اول کار را با زمان نزدیک (مثلاً دو دقیقهٔ بعد) بنویسید، از اجرای آن مطمئن شوید و بعد زمان نهایی را تنظیم کنید.

خواندن یک خط crontab
  1. 30 = دقیقه

    دقیقهٔ سی‌ام از ساعت.

  2. 3 = ساعت

    ساعت ۳ بامداد به وقت سرور.

  3. * = روز ماه

    هر روز ماه.

  4. * = ماه

    همهٔ ماه‌ها.

  5. * = روز هفته

    همهٔ روزهای هفته؛ پس نتیجه: هر شب ساعت ۳:۳۰.

شکل ۲ عبارت 30 3 * * * یعنی هر شب ساعت ۳:۳۰ بامداد به وقت منطقهٔ زمانی سرور.

پوشه‌های cron.daily و cron.weekly و نقش anacron

علاوه بر crontab کاربران، سیستم چند پوشهٔ آماده دارد: /etc/cron.hourly، /etc/cron.daily، /etc/cron.weekly و /etc/cron.monthly. هر اسکریپت اجرایی که در این پوشه‌ها قرار دهید، با همان دوره اجرا می‌شود و نیازی به نوشتن عبارت زمان ندارید. بسته‌هایی مثل logrotate و به‌روزرسانی خودکار امنیتی هم کارهای روزانهٔ خود را همین‌جا قرار می‌دهند.

دو نکته را رعایت کنید: نام فایل در این پوشه‌ها نباید نقطه یا پسوند داشته باشد (مثلاً backup نه backup.sh)، وگرنه ابزار run-parts آن را نادیده می‌گیرد؛ و فایل باید مجوز اجرا داشته باشد (chmod +x). با دستور run-parts --test /etc/cron.daily می‌بینید کدام فایل‌ها اجرا خواهند شد.

روی اوبونتو، اجرای پوشه‌های روزانه و هفتگی را ابزاری به نام anacron مدیریت می‌کند. مزیت anacron این است که اگر سرور در زمان مقرر خاموش بوده، کار جامانده را پس از روشن شدن اجرا می‌کند؛ ویژگی‌ای که cron معمولی ندارد.

مهم‌ترین دام: محیط اجرای cron

بیشترین شکایت از cron این است: «اسکریپت را دستی اجرا می‌کنم کار می‌کند، اما در cron اجرا نمی‌شود.» علت تقریباً همیشه تفاوت محیط است. cron با یک محیط حداقلی اجرا می‌شود:

  • متغیر PATH بسیار کوتاه است؛ دستورهایی مثل docker، node یا pm2 ممکن است پیدا نشوند.
  • پوشهٔ جاری، پوشهٔ خانهٔ کاربر است، نه پوشهٔ اسکریپت.
  • متغیرهای محیطی که در .bashrc تعریف کرده‌اید وجود ندارند.
  • پوستهٔ پیش‌فرض sh است، نه bash.

راه‌حل‌ها:

# در ابتدای crontab
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# در خود دستور به پوشهٔ پروژه بروید
*/10 * * * * cd /opt/myapp && ./venv/bin/python task.py >> /var/log/myapp-task.log 2>&1

قاعدهٔ ساده: در crontab همیشه مسیر کامل فایل‌ها و برنامه‌ها را بنویسید. مسیر هر برنامه را با which پیدا کنید؛ مثلاً which docker.

علامت % هم در crontab معنای خاصی دارد (پایان خط) و باید با بک‌اسلش نوشته شود. برای مثال در نام فایل تاریخ‌دار: $(date +\%F).

منطقهٔ زمانی سرور را بدانید

cron زمان‌ها را بر اساس ساعت سیستم تفسیر می‌کند. بسیاری از سرورها، به‌خصوص سرورهای خارج، به‌طور پیش‌فرض روی UTC تنظیم شده‌اند. اگر بکاپ را برای «ساعت ۳ بامداد» تنظیم کرده‌اید ولی در زمان دیگری اجرا می‌شود، منطقهٔ زمانی را بررسی کنید:

timedatectl
sudo timedatectl set-timezone Asia/Tehran
sudo systemctl restart cron

اگر چند سرور در کشورهای مختلف دارید، نگه داشتن همه روی UTC و حساب کردن اختلاف ساعت در ذهن، معمولاً از تغییر منطقهٔ زمانی کم‌دردسرتر است.

جلوگیری از اجرای هم‌زمان و نظارت بر کارها

اگر کاری هر پنج دقیقه اجرا می‌شود ولی گاهی بیش از پنج دقیقه طول می‌کشد، نسخهٔ بعدی پیش از تمام شدن قبلی شروع می‌شود و ممکن است داده خراب شود یا بار سرور بالا برود. ابزار flock با یک فایل قفل از این وضعیت جلوگیری می‌کند:

*/5 * * * * flock -n /tmp/sync.lock /opt/scripts/sync.sh >> /var/log/sync.log 2>&1

گزینهٔ -n یعنی اگر قفل گرفته شده، این نوبت بی‌صدا رد شود.

برای اینکه بفهمید cron کاری را اجرا کرده یا نه، لاگ سیستم را ببینید:

grep CRON /var/log/syslog | tail -n 20
journalctl -u cron --since today

برای کارهای حیاتی مثل بکاپ، به لاگ اکتفا نکنید؛ در انتهای اسکریپت بررسی کنید که فایل بکاپ ساخته شده و حجمش منطقی است و در صورت خطا برای خودتان پیام بفرستید (مثلاً از طریق یک ربات تلگرام).

root@server: ~
$ crontab -lSHELL=/bin/bash30 3 * * * /usr/local/bin/backup-db.sh >> /var/log/backup-db.log 2>&1$ grep CRON /var/log/syslog | tail -n 2... CRON[...]: (root) CMD (/usr/local/bin/backup-db.sh >> ...)$ timedatectl | grep zoneTime zone: Asia/Tehran (+0330)$ 
شکل ۳ crontab -l کارها را نشان می‌دهد و syslog تأیید می‌کند که cron آن‌ها را اجرا کرده است.

cron یا تایمر systemd؟

روی توزیع‌های جدید، تایمرهای systemd جایگزین قدرتمندتری برای cron هستند. مزیت‌هایشان: لاگ کامل در journald، امکان اجرای کارهای جامانده پس از روشن شدن سرور (Persistent=true)، وابستگی به سرویس‌های دیگر و محدود کردن منابع. در مقابل، cron ساده‌تر است و یک خط کافی است.

قاعدهٔ عملی: برای کارهای کوتاه و ساده cron کافی است. برای سرویس‌هایی که باید دائماً اجرا شوند، cron انتخاب درستی نیست و باید سرویس systemd بسازید؛ نمونهٔ آن را در اجرای دائمی ربات تلگرام با systemd ببینید. اجرای @reboot در cron برای برنامه‌های دائمی جایگزین مناسبی نیست، چون اگر برنامه از کار بیفتد کسی آن را دوباره اجرا نمی‌کند.

نکته‌های امنیتی

  • اسکریپت‌هایی که root اجرا می‌کند نباید توسط کاربران دیگر قابل‌ویرایش باشند؛ مالکیت و مجوز آن‌ها را با ls -l بررسی کنید.
  • رمزها را مستقیم در crontab ننویسید؛ آن‌ها را در فایلی با مجوز 600 نگه دارید و از اسکریپت بخوانید.
  • crontab ناشناخته یکی از روش‌های رایج ماندگاری بدافزار است. اگر سرور مشکوک رفتار می‌کند، crontab همهٔ کاربران و پوشه‌های /etc/cron.* را بررسی کنید. فهرست کامل کنترل‌ها در چک‌لیست امنیت سرور جدید آمده است.

برای یادگیری دستورهای پایهٔ مدیریت فایل و فرایند که در اسکریپت‌های cron به کار می‌روند، دستورات پرکاربرد لینوکس برای سرور را ببینید. اگر کار زمان‌بندی‌شده‌ای مثل پردازش شبانه فقط چند ساعت منابع زیاد لازم دارد، می‌توانید آن را روی یک سرور ساعتی جداگانه اجرا کنید و پس از پایان کار حذفش کنید.

سؤالات متداول

چرا کار cron اجرا نمی‌شود ولی دستی کار می‌کند؟

معمولاً به‌دلیل محیط حداقلی cron است: PATH کوتاه، پوشهٔ جاری متفاوت و نبود متغیرهای محیطی. مسیر کامل برنامه‌ها را بنویسید، در دستور به پوشهٔ پروژه بروید و خروجی را در لاگ ذخیره کنید تا خطای واقعی را ببینید.

چطور یک کار را هر ۳۰ ثانیه اجرا کنم؟

کوچک‌ترین واحد cron یک دقیقه است. می‌توانید دو خط بنویسید که یکی بلافاصله و دیگری با sleep 30 اجرا شود، اما برای چنین فاصله‌هایی تایمر systemd یا یک حلقه داخل یک سرویس دائمی انتخاب تمیزتری است.

crontab کاربران کجا ذخیره می‌شود؟

در پوشهٔ /var/spool/cron/crontabs روی اوبونتو و دبیان. این فایل‌ها را مستقیم ویرایش نکنید و همیشه از crontab -e استفاده کنید، چون این دستور نگارش را بررسی و سرویس را مطلع می‌کند.

تفاوت crontab -e و فایل‌های /etc/cron.d چیست؟

crontab -e مخصوص یک کاربر است و ستون کاربر ندارد. فایل‌های /etc/cron.d و /etc/crontab سراسری هستند و بعد از پنج فیلد زمان باید نام کاربر اجراکننده را هم بنویسید. برای کارهای بسته‌های نرم‌افزاری معمولاً از cron.d استفاده می‌شود.

آماده‌اید؟ سرورتان را بسازید.

از ۱٬۲۰۰ تومان در ساعت · پرداخت ریالی

سرورتان را همین حالا بسازید.

ساعتی بپردازید. هر وقت خواستید حذف کنید.