سرور وقتی ارزشش را نشان میدهد که در خواب شما کار کند: پشتیبانگیری، چرخش لاگها، تمدید گواهیها، گزارشی در ساعت نه. لینوکس برای این کار دو زمانبند دارد. 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 خروجی کار را برای کاربر ایمیل میکند. ایمیج ما سرور ایمیل ندارد، پس journal نوشت (CRON) info (No MTA installed, discarding output) و خروجی از بین رفت. خودتان هدایتش کنید، مثل مثال اول با >> /var/log/backup.log 2>&1.
تلهٔ 2: علامت درصد. در crontab علامت % دستور را تمام میکند و بقیه را به ورودی استاندارد تبدیل میکند. ما date +%F > /tmp/today را زمانبندی کردیم. journal نشان میدهد 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 | |
|---|---|---|
| راهاندازی | 1 خط | 2 فایل |
| لاگ | فقط اگر خروجی را هدایت کنید | 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 تایمری که روی سرور تازه اجرا میشوند.
نظرات
هنوز نظری نیست. اولین نفر باشید.