systemd Timer ابزار زمانبندی داخلی systemd است که در سرورهای لینوکسی میتواند بسیاری از Cron Jobها را با کنترل بهتر، لاگ یکپارچه و امکان جبران اجرای ازدسترفته جایگزین کند. در این روش، فایل .timer تعیین میکند کار چه زمانی اجرا شود و فایل .service مشخص میکند چه دستوری اجرا شود.
خلاصه سریع: اگر فقط یک زمانبندی ساده و قابلحمل بین سیستمهای یونیکسی میخواهید، Cron هنوز انتخاب خوبی است. اگر سرور شما systemd دارد و به لاگ شفاف، وابستگی سرویسها، Persistent=true، زمانبندی بر اساس بوت یا پراکندگی بار نیاز دارید، systemd Timer معمولاً انتخاب قویتری است.
systemd Timer چیست و چه تفاوتی با Cron دارد؟
Timer یکی از انواع unitهای systemd است. برخلاف Cron که زمان و فرمان اجرا را معمولاً در یک خط crontab مینویسیم، systemd مسئولیت «چه زمانی» و «چه کاری» را جدا میکند. این جداسازی باعث میشود وضعیت اجرا، خطاها و وابستگیها راحتتر مدیریت شوند. اگر با خود systemd آشنا نیستید، ابتدا مقاله بررسی systemd و سرویسمنیجمنت مدرن را ببینید.
| ویژگی | Cron | systemd Timer |
|---|---|---|
| سادگی تنظیم | بسیار ساده | دو unit جداگانه |
| لاگ | وابسته به تنظیم خروجی/syslog | یکپارچه با journal |
| اجرای ازدسترفته | بهصورت پیشفرض خیر | با Persistent=true برای timer تقویمی |
| زمان نسبت به بوت | محدود | OnBootSec و گزینههای monotonic |
| وابستگی سرویسها | محدود | قابلیتهای کامل systemd |
| پراکندگی زمان اجرا | دستی | RandomizedDelaySec |
| قابلیت حمل | بالاتر در Unix/Linux | مخصوص سیستمهای دارای systemd |
برای یادگیری ساختار خود Cron نیز مقاله آموزش جامع Cron Job در لینوکس را بخوانید.
ساختار یک systemd Timer چگونه است؟
در حالت معمول دو فایل همنام داریم؛ برای مثال backup-home.timer و backup-home.service. Timer زمان را کنترل میکند و Service اسکریپت واقعی را اجرا میکند. اگر در timer گزینه Unit= را مشخص نکنید، systemd معمولاً service همنام را فعال میکند.

آموزش ساخت systemd Timer برای بکاپ روزانه
فرض کنید اسکریپت بکاپ شما در مسیر /usr/local/sbin/backup-home.sh قرار دارد و میخواهید هر روز حدود ساعت 03:15 اجرا شود.
1. ساخت Service Unit
فایل زیر را بسازید:
sudo nano /etc/systemd/system/backup-home.serviceمحتوای نمونه:
[Unit]
Description=Daily home backup job
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/backup-home.sh
User=rootType=oneshot برای کاری مناسب است که اجرا میشود، تمام میشود و لازم نیست بهصورت daemon در پسزمینه باقی بماند. مسیر ExecStart را همیشه کامل بنویسید.
2. ساخت Timer Unit
sudo nano /etc/systemd/system/backup-home.timer[Unit]
Description=Run home backup every day
[Timer]
OnCalendar=*-*-* 03:15:00
Persistent=true
RandomizedDelaySec=10m
[Install]
WantedBy=timers.targetOnCalendar زمان تقویمی را تعیین میکند. Persistent=true باعث میشود اگر اجرای تقویمی بهدلیل خاموش بودن سیستم از دست رفت، پس از فعال شدن دوباره timer بررسی شود و اجرای جاافتاده انجام شود. RandomizedDelaySec=10m نیز زمان را تا ده دقیقه تصادفی عقب میاندازد؛ در چند سرور این کار جلوی شروع همزمان بار سنگین را میگیرد.
3. بررسی عبارت زمانی قبل از فعالسازی
systemd-analyze calendar '*-*-* 03:15:00'این دستور زمان اجرای بعدی را نشان میدهد و قبل از قرار دادن تنظیم در سرور Production کمک میکند خطای عبارت تقویمی را پیدا کنید.
4. Reload و فعالسازی Timer
sudo systemctl daemon-reload
sudo systemctl enable --now backup-home.timerدر این مرحله خود timer باید فعال باشد؛ لازم نیست service را enable کنید، چون timer آن را در زمان مقرر اجرا میکند.
چطور اجرای Timer را بررسی کنیم؟
برای مشاهده timerها و زمان اجرای بعدی:
systemctl list-timers --allو برای وضعیت دقیق:
systemctl status backup-home.timer
systemctl status backup-home.serviceلاگ اجرای job نیز بهسادگی از journal قابل خواندن است:
journalctl -u backup-home.service --since todayقبل از منتظر ماندن برای زمان واقعی، service را یک بار دستی تست کنید:
sudo systemctl start backup-home.service
systemctl status backup-home.serviceمهاجرت یک Cron Job به systemd Timer
فرض کنید در crontab این خط را دارید:
15 3 * * * /usr/local/sbin/backup-home.shمعادل مفهومی آن در systemd همان Service و Timer بالاست: فرمان از crontab به ExecStart منتقل میشود و زمان 03:15 در OnCalendar قرار میگیرد. بعد از تست موفق timer، خط Cron قدیمی را حذف یا کامنت کنید تا job دوبار اجرا نشود.
زمانبندی نسبی با OnBootSec و OnUnitActiveSec
systemd فقط تقویم نیست. برای مثال، اگر میخواهید کاری 10 دقیقه بعد از بوت و سپس هر یک ساعت پس از آخرین فعالشدن اجرا شود:
[Timer]
OnBootSec=10m
OnUnitActiveSec=1hاین گزینهها monotonic هستند و برای maintenanceهای دورهای که به ساعت دیواری وابسته نیستند کاربرد دارند.
Persistent، AccuracySec و RandomizedDelaySec را درست بفهمیم
- Persistent=true: برای timerهای مبتنی بر
OnCalendarتاریخ آخرین trigger را نگه میدارد و اجرای جاافتاده را پس از بازگشت timer جبران میکند. - AccuracySec: پنجره دقت اجرای timer را کنترل میکند. این گزینه را با «تضمین اجرای دقیق در همان ثانیه» اشتباه نگیرید؛ systemd میتواند wake-upها را برای بهرهوری بهتر همزمان کند.
- RandomizedDelaySec: اجرای timer را در یک بازه تصادفی پخش میکند؛ برای بکاپ، آپدیت یا maintenance روی تعداد زیادی VPS بسیار مفید است.
Best Practice برای Timerهای سرور
- فرمانهای طولانی را داخل
ExecStartانباشته نکنید؛ اسکریپت قابل تست و نسخهبندی بسازید. - مسیر فایلها و باینریها را مطلق بنویسید؛ محیط systemd با shell تعاملی شما یکسان نیست.
- در Service در صورت امکان از کاربر کمدسترسی استفاده کنید و فقط برای کارهای واقعاً سیستمی سراغ root بروید.
- برای timerهای مهم، لاگ و exit code را مانیتور کنید؛ «فعال بودن timer» بهتنهایی به معنی موفق بودن job نیست.
- در Fleet چندسروری از RandomizedDelaySec استفاده کنید تا CPU، دیسک یا مقصد بکاپ همزمان تحت فشار قرار نگیرد.
- قبل از حذف Cron قدیمی، service را دستی و سپس timer را در یک بازه کوتاه تست کنید.
عیبیابی مشکلات رایج systemd Timer
| مشکل | بررسی | راهحل |
|---|---|---|
| Timer فعال است ولی job اجرا نشده | systemctl list-timers --all | زمان NEXT، عبارت OnCalendar و timezone را بررسی کنید. |
| Timer trigger شده ولی نتیجه نداریم | systemctl status backup-home.service | خطای Service را رفع کنید؛ Timer فقط trigger است. |
| فرمان در SSH کار میکند ولی در Service نه | journalctl -u backup-home.service | PATH، environment، permission و مسیر مطلق را بررسی کنید. |
| بعد از ویرایش فایل تغییر اعمال نشده | وضعیت unit | sudo systemctl daemon-reload را اجرا کنید. |
| اجرای زمان خاموش بودن سرور از دست رفته | نوع timer | برای OnCalendar در صورت نیاز Persistent=true بگذارید. |
Cron بهتر است یا systemd Timer؟
برای یک job بسیار ساده و محیطی که قابلیت حمل بین Unixها مهم است، Cron کماصطکاکتر است. روی VPSهای مدرن مبتنی بر systemd، زمانی که مشاهدهپذیری، مدیریت خطا، وابستگی، اجرای پس از بوت و کنترل دقیقتر مهم است، Timer انتخاب ساختاریافتهتری محسوب میشود. هدف جایگزینی کورکورانه همه Cronها نیست؛ ابزار را بر اساس نیاز عملی انتخاب کنید.
سوالات متداول
آیا systemd Timer از Cron دقیقتر است؟
نه بهصورت مطلق. systemd امکانات بیشتری برای کنترل زمان دارد، اما AccuracySec و سیاستهای زمانبندی میتوانند اجرای دقیق در همان ثانیه را تغییر دهند. برای اکثر کارهای مدیریتی سرور، این رفتار مطلوب است.
آیا Timer بعد از خاموش بودن سرور اجرای جاافتاده را انجام میدهد؟
برای timerهای تقویمی، اگر Persistent=true فعال باشد، systemd میتواند trigger جاافتاده را هنگام فعال شدن دوباره جبران کند.
چطور زمان اجرای بعدی Timer را ببینیم؟
از systemctl list-timers --all استفاده کنید. ستون NEXT زمان اجرای بعدی را نشان میدهد.
آیا میتوان systemd Timer را برای کاربر عادی ساخت؟
بله، systemd از user units نیز پشتیبانی میکند و میتوان با systemctl --user آنها را مدیریت کرد؛ رفتار دقیق در زمان logout به تنظیمات session و linger وابسته است.
آیا Service را هم باید enable کنیم؟
در سناریوی معمول نه. Timer را enable میکنید و همان Timer در زمان مقرر Service را start میکند.
جمعبندی
systemd Timer با جداسازی زمانبندی از اجرای واقعی job، مدیریت وظایف دورهای را در سرور لینوکس قابلمشاهدهتر و قابلکنترلتر میکند. مهاجرت را از jobهای مهمی شروع کنید که به لاگ، جبران اجرای ازدسترفته یا وابستگیهای systemd نیاز دارند و بعد از تست، Cron قدیمی را حذف کنید.
اگر برای اجرای سرویسهای لینوکسی، بکاپ خودکار یا jobهای دورهای به محیط مستقل نیاز دارید، پلنهای سرور مجازی وان سرور را میتوانید بررسی کنید.
منابع
- systemd.timer — مستندات رسمی systemd در freedesktop.org
- Working with systemd Timers — مستندات SUSE Linux Enterprise Server
- systemd/Timers — ArchWiki
