cron در لینوکس: زمانبندی تکرارشوندهٔ کارها
crontab، نحو زمانبندی، محیط محدود cron، لاگ، و تفاوت با systemd timer برای کارهای تکراری در لینوکس.
Founder & product engineer

بکاپ شبانه، پاکسازی موقت، گزارش روزانه، و همگامسازی سبک — کارهایی که باید سر وقت و بدون حضور انسان اجرا شوند. cron زمانبند کلاسیک یونیکس برای این الگوی «در این دقیقه/ساعت/روز» است. هنوز همهجا هست، نحو آن ساده به نظر میرسد، و بیشتر باگهایش از محیط اجرا میآید نه از خود زمانبندی.
روی سیستمهای جدید گاهی systemd timer جایگزین یا مکمل است؛ با این حال دانستن crontab برای سرورهای موجود و کانتینرهای سنتی ضروری میماند.

پاسخ کوتاه
ویرایش جدول کاربر: `crontab -e`. پنج فیلد زمان + فرمان. لاگ و ایمیل را جدی بگیرید؛ خروجی را با ریدایرکت صریح مدیریت کنید. PATH و cwd در cron با ترمینال شما یکی نیست — مسیر مطلق بدهید. برای سرویسهای مدرن با وابستگی واحدها، systemd timer را هم ارزیابی کنید. قبل از production، روی بازهٔ کوتاه بیازمایید و همپوشانی اجرا را کنترل کنید.
cron فقط زمان را قول میدهد؛ موفقیت کار به محیط، قفل، و مشاهدهپذیری وابسته است.
دیدن و ویرایش crontab
bash
crontab -l crontab -e sudo crontab -u deploy -l
هر کاربر جدول خودش را دارد. ویرایش با ادیتور پیشفرض (`$EDITOR`). نحو غلط ممکن است رد شود؛ بعد از ذخیره یک بار `-l` را مرور کنید.
نحو پنجفیلدی
bash
# min hour day-of-month month day-of-week command # 0-59 0-23 1-31 1-12 0-7 (0 و 7 یکشنبه) */5 * * * * /usr/local/bin/health-check.sh 0 3 * * * /usr/local/bin/backup.sh 30 4 * * 1 /usr/local/bin/weekly.sh
`*/5` هر پنج دقیقه. بازه و لیست مثل `1,15` و `1-5` بسته به پیادهسازی پشتیبانی میشوند. از `@daily` و `@reboot` در صورت پشتیبانی cron سیستم هم میتوانید استفاده کنید — مستند همان نسخه را ببینید.
محیط محدود: ریشهٔ بیشتر شکستها
- PATH کوتاه؛ فرمانهای /usr/local/bin دیده نمیشوند.
- cwd معمولاً HOME است نه پوشهٔ پروژه.
- متغیرهای جلسهٔ SSH و bashrc لود نمیشوند.
- گاهی شل /bin/sh نه bash.
bash
0 2 * * * /bin/bash /usr/local/bin/job.sh >>/var/log/job.log 2>&1
داخل اسکریپت، PATH را خودتان set کنید یا از مسیر مطلق همهٔ باینریها استفاده کنید.
لاگ و مشاهده
bash
# روی خیلی از سیستمها: grep CRON /var/log/syslog | tail journalctl -u cron -n 50 --no-pager # نام سرویس ممکن است cron یا crond باشد
خود cron معمولاً فقط شروع/خطاهای زمانبند را میگوید؛ منطق اپ باید به فایل یا سامانهٔ لاگ بنویسد. بدون ریدایرکت، خروجی ممکن است به ایمیل محلی برود یا دور ریخته شود.
جلوگیری از همپوشانی
اگر جاب طولانیتر از فاصلهٔ زمانبندی شود، دو نمونه همزمان ممکن است قفل دیتابیس یا فایل را خراب کنند. از flock استفاده کنید:
bash
*/5 * * * * flock -n /tmp/job.lock /usr/local/bin/job.sh >>/var/log/job.log 2>&1
مجوز، کاربر، و امنیت
- کمترین کاربر لازم؛ نه همه چیز زیر root مگر ضروری.
- اسکریپتها نباید برای دیگران قابلنوشتن باشند.
- secret را داخل crontab خط فرمان نگذارید؛ از فایل مجوزدار بخوانید.
bash
ls -l /usr/local/bin/backup.sh sudo crontab -u root -l | head
crontab سیستم و /etc/cron.*
bash
ls /etc/cron.d /etc/cron.daily /etc/cron.hourly 2>/dev/null cat /etc/crontab | head
بستهها گاهی فایل در /etc/cron.d میگذارند (با فیلد کاربر اضافه). برای کار اپ خودتان، crontab کاربر سرویس معمولاً تمیزتر از قاطی کردن با سیستم است مگر سیاست سازمان خلافش باشد.
جدول در برابر systemd timer
| نیاز | ترجیح تقریبی |
|---|---|
| زمانبندی سادهٔ کاربر | cron |
| وابستگی به واحد شبکه/مونت | systemd timer |
| لاگ یکپارچه با journal | systemd timer |
| قابلحمل روی سیستم بدون systemd | cron |
| تقویم پیچیده و jitter | systemd timer اغلب قویتر |
الگوی اسکریپت مقاوم برای cron
bash
cat > /usr/local/bin/job.sh << 'EOF' #!/bin/bash set -euo pipefail PATH=/usr/local/bin:/usr/bin:/bin cd /var/lib/myapp exec ./bin/run-job EOF chmod 750 /usr/local/bin/job.sh
set -euo pipefail و PATH ثابت، نیمی از تیکتهای «روی سرور کار نکرد» را کم میکند.
اشتباههای رایج
- نوشتن فرمان نسبی بدون cd.
- فرض وجود nvm/pyenv بدون init در اسکریپت.
- هر دقیقه جاب سنگین بدون flock.
- ویرایش /var/spool/cron دستی بهجای crontab -e.
- فراموش تفاوت منطقهٔ زمانی سیستم.
منطقهٔ زمانی
bash
timedatectl # برخی cronها از CRON_TZ پشتیبانی میکنند — مستند نسخه را ببینید
اگر سرور UTC است و شما تقویم تهران در سر دارید، ساعت ۳ ممکن است آن ۳ای نباشد که فکر میکنید. صریح باشید.
آزمایش قبل از production
- اسکریپت را دستی با همان کاربر cron اجرا کنید: `sudo -u deploy /usr/local/bin/job.sh`.
- crontab را موقتاً روی `*/1` با flock بگذارید و لاگ را ببینید.
- به فاصلهٔ نهایی برگردانید.
- هشدار مانیتورینگ روی «آخرین موفقیت» بگذارید نه فقط «فرایند زنده».
مانیتورینگ «آخرین موفقیت»
زنده بودن crond کافی نیست. جاب باید در انتها یک نشانهٔ موفقیت بنویسد (فایل زمان یا متریک). هشدار را روی کهنه شدن آن نشانه بگذارید تا شکست خاموش وسط شب دیده شود.
bash
date -Is > /var/lib/myapp/job.last_ok # monitoring: alert if mtime older than threshold
جابهای وابسته به شبکه
در بوت، @reboot ممکن است قبل از آمادهشدن DNS/شبکه اجرا شود. یا تأخیر و retry داخل اسکریپت بگذارید یا از systemd timer با وابستگی شبکه استفاده کنید. شکست اول را در لاگ بهعنوان «موقت» برچسب بزنید تا با خطای منطقی قاطی نشود.
بازنشستگی جاب قدیمی
crontab محل انباشت تاریخ است. هر ربع، جابهای بدون مالک و بدون لاگ را مرور و حذف کنید. جاب یتیم یکی از منابع بار عجیب دیسک و ترافیک است.
bash
crontab -l ls -lt /var/log/ | head
مستند مالکیت جاب
بالای هر بلوک crontab یک توضیح با نام تیم، تیکت، و اثر شکست بگذارید. crontab بدون مالک در حادثه پیدا میشود وقتی دیگر کسی یادش نیست چرا هر شب curl به سرویس خارجی میرود.
bash
# team: payments | ticket: OPS-123 | on-fail: page on-call 0 1 * * * flock -n /tmp/pay-reconcile.lock /usr/local/bin/reconcile.sh >>/var/log/reconcile.log 2>&1
همین توضیح را در runbook کپی کنید. هماهنگی انسانها بخش فراموششدهٔ cron است.
خلاصه
cron زمانبند تکرار است با نحو فشرده و محیط فقیر. مسیر مطلق، ریدایرکت لاگ، flock، کاربر کمدسترسی، و آزمایش با همان هویت اجرا، آن را قابل اعتماد میکند. وقتی وابستگی به واحدهای systemd دارید، timer را هم بسنجید — ولی crontab را همچنان بخوانید.
سوالات متداول
چرا جاب اجرا نشد؟
نحو، کاربر اشتباه، PATH، مجوز اسکریپت، یا سرویس cron متوقف. journal/syslog و `systemctl status cron` را ببینید.
چطور هر ۲ دقیقه در روز کاری؟
مثلاً `*/2 * * * 1-5` برای دوشنبه تا جمعه — با فرض تعریف day-of-week سیستم شما.
آیا @reboot بلافاصله بعد از شبکه است؟
نه لزوماً؛ فقط بعد از شروع cron. برای وابستگی شبکه، systemd timer با After=network-online هدف دقیقتری است.
منابع و مراجع
- crontab(1): https://man7.org/linux/man-pages/man1/crontab.1.html
- crontab(5): https://man7.org/linux/man-pages/man5/crontab.5.html
- cron(8): https://man7.org/linux/man-pages/man8/cron.8.html
- systemd.timer(5): https://www.freedesktop.org/software/systemd/man/latest/systemd.timer.html
- flock(1): https://man7.org/linux/man-pages/man1/flock.1.html
Author
Soheil Ebrahimpour is the founder of FutureForge. He works on product design, architecture, and getting custom software into production.
Related notes
If you are unsure about architecture or the build path, we can talk about the project.
Describe the problem and the constraints. If there is a fit, we will schedule a conversation.




