WIUNIX ACADEMY
زمانبندی با systemd timer؛ نوبت ازدسترفته و اجرای تکراری رو مدیریت کن
صفحهٔ 3 از 4؛ قبل از ادامه، مراحل قبلی و چیزهایی رو که لازم داری مرور کن.
آموزش متناسب با محیط تو
کجا اجرا میکنی؟
سیستمعامل و نسخهٔ سرورت رو انتخاب کن تا مراحل، دستورها و راهحلهای همون محیط رو ببینی.
آموزش متناسب با مقادیر تو
تنظیمات این آموزش
مقادیر نمونه رو با مشخصات سرورت عوض کن تا متن و دستورها با هم تغییر کنن. رمز، کلید خصوصی و توکن اینجا وارد نکن. مقدارها فقط توی همین زبانه میمونن و به سرور یا لینک اشتراکگذاری فرستاده نمیشن. قبل از اجرا، DNS، گواهیها و تنظیمات دسترسی شبکه رو روی سرورت بررسی کن.
اگر آیپی، دامنه یا پورتهای نمونه با سرورت فرق دارن، بخش تنظیمات پایین رو باز کن. مقدارها رو عوض کن و «اعمال در آموزش» رو بزن؛ بعد دستورهای تازه رو کپی کن.
تنظیم مقادیر برای محیط من3 مقدار قابلتغییر
قدم بعدی
اگر timer شروع کرد ولی کار تموم نشد
نتیجهٔ سرویس و لاگ حوالی همان نوبت رو بخون. فایل مفقود، اشکال نحو، تمامشدن مهلت، ردشدن دسترسی پوشهٔ داده یا فایل نهایی خراب، خطای برنامه است و با درستکردن عبارت تقویمی رفع نمیشه. قبل از پاککردن وضعیت failed، پیامهای اولین شکست رو نگه دار.
فایل این تمرین نتیجهٔ بررسی بکاپ نیست. برای نمونه، خود فایل کوچک و تاریخش رو ببین. برای کار واقعی، قبل از تکرار سراغ روش اعتبارسنجی و بازیابی خودش برو. لاگ نمیتونه انجام کاری رو ثابت کنه که برنامه ثبت نهایی نکرده.
ترمینال میزبان آزمایشی با دسترسی مجاز
systemctl status 'academy-daily-marker.service' --no-pager
systemctl show 'academy-daily-marker.service' -p Result -p ExecMainCode -p ExecMainStatus -p TimeoutStartUSec
sudo journalctl -u 'academy-daily-marker.service' -u 'academy-daily-marker.timer' --since '-1 hour' --no-pager -n 100
sudo ls -la '/var/lib/academy-daily-marker/'شکست به کد خروج، مهلت، مسیر یا پیام سیاست دسترسی وصل شده. کد خروج غیرصفر همچنان اجرای ناموفق حساب میشه.
قدم بعدی
محدودیت میزبان رو با مشکل timer قاطی نکن
ردشدن دسترسی ممکنه از مجوز معمولی فایل یا پروفایل فعال AppArmor بیاد و ربطی به ساعت اجرا نداشته باشه. پیام کرنل رو با همین کار و زمان شکست تطبیق بده. برای عبور از تمرین، اجرای سیاست امنیتی رو خاموش نکن.
اسکریپت باید متعلق به root و برای هویت موقت قابلخوندن باشه. قبل از دستکاری محدودیتهای سرویس، نبودن مفسر یا دسترسناپذیربودن مسیر رو بررسی کن. حتی با فایل timer یکسان، سیاست بسته و پروفایل محلی میتونه بین میزبانها فرق داشته باشه.
ترمینال میزبان آزمایشی با دسترسی مجاز
sudo journalctl -k --since '-15 min' --no-pager -n 100
sudo stat -c '%U %G %a %n' '/usr/local/libexec/academy-daily-marker.sh' '/etc/systemd/system/academy-daily-marker.service'خطای مجوز یا سیاست میزبان جداگانه شناسایی شده و اجرای سیاست امنیتی تغییری نکرده.
قدم بعدی
نوبتهای بعدی رو متوقف کن؛ اجرای فعلی رو هم ببین
اگر کار شکست خورده یا باید زمانبندی رو عوض کنی، اول timer رو متوقف و غیرفعال کن. توقف timer سرویسی رو که از قبل در حال اجراست متوقف نمیکنه. وضعیت سرویس رو جدا ببین و اگر ادامهدادنش بیخطره، صبر کن تموم بشه؛ غیرفعالشدن زمانبندی به معنی لغو کار نیست.
کار کوچک این تمرین رو در صورت نیاز میشه متوقف کرد، اما بکاپ یا مهاجرت دادهٔ واقعی روش توقف خودش رو لازم داره. دادهٔ نیمهکاره و لاگ رو نگه دار. پردازش نامرتبط رو فقط به خاطر شباهت اسمش به این نمونه متوقف نکن.
ترمینال میزبان آزمایشی با دسترسی مجاز
sudo systemctl disable --now 'academy-daily-marker.timer' || exit 1
systemctl show 'academy-daily-marker.timer' -p ActiveState -p SubState
systemctl show 'academy-daily-marker.service' -p ActiveState -p SubState
sudo journalctl -u 'academy-daily-marker.service' --since '-30 min' --no-pager -n 60
timer غیرفعال و متوقف شده و میدونی سرویس مستقل از اون هنوز در حال اجراست یا تموم شده.
قدم بعدی
بعد از رفع علت، دوباره امتحان کن
در همین نمونه، اشکال فایل یا سیاست دسترسی رو رفع کن، فایلها رو دوباره بررسی کن و از راه سرویس تلاش تازه انجام بده. پاککردن وضعیت failed فقط شکست ثبتشده و شمارندهٔ محدودیت شروع systemd رو پاک میکنه؛ اسکریپت رو تعمیر یا کار نیمهکاره رو برنمیگردونه.
قبل از فعالکردن دوبارهٔ timer، نتیجهٔ تازه رو ببین. timer تقویمیِ Persistent ممکنه با فعالشدن یک نوبت جبرانی هم درخواست کنه. فایل روزانه باعث میشه تکرار کار امروز بیضرر باشه؛ برای بازیابی خودکارِ برنامهٔ واقعی هم به رفتار مشابه نیاز داری.
ترمینال میزبان آزمایشی با دسترسی مجاز
sudo systemctl reset-failed 'academy-daily-marker.service' || exit 1
sudo systemctl start 'academy-daily-marker.service' || exit 1
sudo systemctl show 'academy-daily-marker.service' -p Result -p ExecMainStatus
sudo journalctl -u 'academy-daily-marker.service' --since '-10 min' --no-pager -n 60
sudo systemctl enable --now 'academy-daily-marker.timer' || exit 1
systemctl is-enabled --quiet 'academy-daily-marker.timer' || exit 1
systemctl is-active --quiet 'academy-daily-marker.timer' || exit 1
systemctl list-timers --all 'academy-daily-marker.timer'
اجرای تازه موفق شده یا انجامشدن کار امروز رو تأیید کرده؛ فقط بعد از اون timer دوباره منتظر است.
قدم بعدی
اختیاری: بهجای ساعت روز، از پایان کار فاصله بگیر
اگر خواستهات «سی دقیقه بعد از پایان کار» است، این جایگزین رو انتخاب کن. timer رو متوقف کن و قبل از ویرایش صبر کن سرویس غیرفعال بشه. یک نسخه از فایل تقویمی همین تمرین نگه میداریم و تمام محتوای فایل رو با پنل بعدی عوض میکنیم؛ تنظیمات تازه رو ته تنظیمات تقویمی اضافه نکن.
اگر فایل پشتیبان از قبل وجود داشته باشه، کپی متوقف میشه. این تغییر فقط برای نمونهٔ همین آموزش است و اجازهٔ جایگزینی timer شخص یا کار دیگری نیست. اگر به این جایگزین نیاز نداری، میتونی مستقیم سراغ معیارهای پایان راهنما بری.
ترمینال میزبان آزمایشی با دسترسی مجاز
sudo systemctl disable --now 'academy-daily-marker.timer' || exit 1
test "$(systemctl show -p ActiveState --value 'academy-daily-marker.service')" = inactive || exit 1
sudo test ! -e '/etc/systemd/system/academy-daily-marker.timer.calendar-backup' || exit 1
sudo cp -p -- '/etc/systemd/system/academy-daily-marker.timer' '/etc/systemd/system/academy-daily-marker.timer.calendar-backup' || exit 1
sudoedit '/etc/systemd/system/academy-daily-marker.timer' || exit 1
timer متوقف شده، سرویس تموم شده و قبل از ویرایش، نسخهٔ همان فایل تقویمی نگه داشته شده.
فاصله رو از پایان اجرا حساب کنیم
گزینهٔ OnBootSec اولین شروع رو برای پنج دقیقه بعد از بوت میذاره؛ اگر موقع شروع timer این زمان گذشته باشه، ممکنه بلافاصله تحریک بشه. بعد، OnUnitInactiveSec سی دقیقه رو از غیرفعالشدن سرویس حساب میکنه. این با OnUnitActiveSec فرق داره که مبدأش شروع فعالسازی است.
اینجا نه OnCalendar داریم و نه Persistent؛ لیست فاصلههای ازدسترفته در خاموشی بازیابی نمیشه. ساعت یکنواخت هم معمولاً هنگام suspend جلو نمیره. اسکریپت هنوز فقط یک فایل برای هر روز UTC میسازه، پس نوبتهای بیشتر، رفتار زمانبندی رو نشون میدن و کار تجاری تکراری تولید نمیکنن.
جایگزین اختیاریِ کل فایل؛ در ترمینال اجرا نکن
[Unit]
Description=Academy completion-relative schedule
[Timer]
OnBootSec=5min
OnUnitInactiveSec=30min
AccuracySec=1s
Unit=academy-daily-marker.service
[Install]
WantedBy=timers.target