فضای آموزشی عملیاتیِ بدون آدم با تابلوی زمان‌بندی systemd، نوبت ازدست‌رفته و فاصله از پایان اجرا

WIUNIX ACADEMY

زمان‌بندی با systemd timer؛ نوبت ازدست‌رفته و اجرای تکراری رو مدیریت کن

یک کار آزمایشیِ تکرارپذیر می‌سازیم، زمان‌بندی روزانهٔ UTC و جبران نوبت ازدست‌رفته رو می‌بینیم و یاد می‌گیریم چه وقت فاصله از پایان اجرا انتخاب بهتریه.

متوسط تا پیشرفته35 دقیقه مطالعهبه‌روزرسانی
محیطت رو انتخاب کن

آموزش متناسب با محیط تو

کجا اجرا می‌کنی؟

سیستم‌عامل و نسخهٔ سرورت رو انتخاب کن تا مراحل، دستورها و راه‌حل‌های همون محیط رو ببینی.

Manjaro rollingبررسی‌شده با مستندات رسمی ·

آموزش متناسب با مقادیر تو

تنظیمات این آموزش

مقادیر نمونه رو با مشخصات سرورت عوض کن تا متن و دستورها با هم تغییر کنن. رمز، کلید خصوصی و توکن اینجا وارد نکن. مقدارها فقط توی همین زبانه می‌مونن و به سرور یا لینک اشتراک‌گذاری فرستاده نمی‌شن. قبل از اجرا، DNS، گواهی‌ها و تنظیمات دسترسی شبکه رو روی سرورت بررسی کن.

اگر آی‌پی، دامنه یا پورت‌های نمونه با سرورت فرق دارن، بخش تنظیمات پایین رو باز کن. مقدارها رو عوض کن و «اعمال در آموزش» رو بزن؛ بعد دستورهای تازه رو کپی کن.

تنظیم مقادیر برای محیط من3 مقدار قابل‌تغییر

از اینجا شروع کن

آخر این آموزش چی خواهیم داشت؟

یک کار آزمایشیِ تکرارپذیر می‌سازیم، زمان‌بندی روزانهٔ UTC و جبران نوبت ازدست‌رفته رو می‌بینیم و یاد می‌گیریم چه وقت فاصله از پایان اجرا انتخاب بهتریه.

سیستم‌عامل‌ها و نسخه‌های پوشش‌داده‌شده

مسیرهای اوبونتو ۲۶٫۱۰ و LTSهای ۲۶٫۰۴ و ۲۴٫۰۴، دبیان ۱۳ و ۱۲، خانوادهٔ RHEL/راکی/آلما ۱۰ و ۹، آرچ و مانجارو پوشش داده شده‌اند. تفاوت ابزار بسته و سیاست میزبان در انتخاب محیط میاد؛ مسیرهای غلتان با تاریخ بررسی و نسخهٔ بسته شناخته می‌شن. این‌ها بررسی مستنداتن، نه ادعای اجرای عملی روی همهٔ سیستم‌ها. timer محلی جای صف پایدار یا تضمین برنامه برای جلوگیری از اثر تکراری نیست.

قبل از شروع

  • یک میزبان آزمایشی با systemd به‌عنوان پردازش شمارهٔ یک، دسترسی مجاز sudo و ویرایشگر آماده برای sudoedit.
  • نام تازه‌ای برای واحدهای تمرین و فضای کوچک داده؛ هیچ فایل یا زمان‌بندی برنامهٔ موجودی جایگزین نمی‌شه.
  • آشنایی با واحدهای systemd، کد خروج برنامه و بررسی لاگ. اجرا و توقف فقط برای نمونهٔ همین آموزش مجازه.

از زمان‌بندی دقیقاً چه انتظاری داریم؟

فرض کن یک کار نگهداری هر شب انجام می‌شه. اگر سرور خاموش باشه چه اتفاقی باید بیفته؟ اگر اجرا شکست بخوره، تکرارش بی‌خطره؟ اگر هنوز تموم نشده باشه و نوبت بعدی برسه چی؟ timer فقط زمان درخواست شروع سرویس رو مشخص می‌کنه؛ تشخیص کار باقی‌مونده و نتیجهٔ اجرای قبلی به خود برنامه مربوطه.

برای روشن‌شدن این تفاوت، یک کار آزمایشی تازه می‌سازیم که برای هر روز UTC فقط یک فایل کوچک ثبت می‌کنه. اول زمان‌بندی روزانه رو می‌بینیم و بعد سراغ فاصله‌ای می‌ریم که از پایان کار حساب می‌شه. این فایل نشونهٔ انجام کار آزمایشیه؛ بکاپ، صورت‌حساب یا تضمین اجرای دقیقاً یک‌باره نیست. روی میزبان آزمایشی کار کن و زمان‌بندی برنامهٔ واقعی رو با این نمونه عوض نکن.

اگر ساعت مشخصی از روز مهمه، تقویم انتخاب مناسبیه. اگر می‌خوای برنامه بعد از هر اجرا مدتی استراحت کنه، فاصله از پایان کار روشن‌تره. timer یک ماشین هم هماهنگ‌کنندهٔ کلاستر نیست؛ برای پردازش تک‌تک رویدادهای ازدست‌رفته به صف یا سازوکار خود برنامه نیاز داری.

مقادیر نمونه رو قبل از کپی‌کردن تنظیم کن

فرم مقادیر نمونه رو باز کن، برای کار یک نام تازه انتخاب کن و ساعت UTC رو بین ۰ تا ۲۳ بذار. بعد مقدارها رو اعمال کن. شروع کار ممکنه تا 300 ثانیه به‌صورت تصادفی عقب بیفته تا چند میزبان هم‌زمان شلوغ نشن؛ این مقدار تضمین زمان پایان نیست. نام کار هم نام فایل‌های سرویس، timer، اسکریپت و پوشهٔ داده رو تعیین می‌کنه، پس نام یک برنامهٔ موجود رو انتخاب نکن.

مقدارها برای همین آموزش و محیط انتخاب‌شده در همین تب می‌مونن. تا وقتی تغییرها رو اعمال یا بازنشانی نکرده باشی، یا مقدار نامعتبر باشه، کپی دستورها متوقف می‌شه. اینجا فقط مقدارهای عمومی وارد کن؛ رمز، توکن و آرگومان خصوصی برنامه جاشون در این فرم نیست. تاریخ فایل آزمایشی همیشه UTC حساب می‌شه، حتی اگر ساعت اجرا رو عوض کنی.

01

قدم بعدی

توزیع و ابزارهای همین میزبان رو بررسی کن

در شاخهٔ فعلی و پشتیبانی‌شدهٔ مانجارو با ارتقای کامل معمولش کار کن؛ تاریخ بررسی این مسیر ۲۰۲۶-۱۱-۰۵ است. بستهٔ مانجارو ممکنه با آرچ روز فرق داشته باشه، پس همین میزبان رو بررسی کن و مخزن آرچ یا بستهٔ timer از AUR وارد نکن. systemd باید مدیر اصلی سیستم باشه.

برای تهیهٔ ابزار کم‌شده، راهنمای ارتقای کامل مانجارو رو دنبال کن و ارتقای ناقص انجام نده. محل فایل واحدهای مدیریتی و طراحی داده با DynamicUser همان است. پروفایل فعال AppArmor یا سیاست محلی جداگانه اثر داره؛ در این تمرین هیچ سیاست کنترل دسترسی اجباری خاموش نمی‌شه.

bash

ترمینال میزبان آزمایشی با دسترسی مجاز

cat /etc/os-release
cat /proc/1/comm
systemd --version
pacman -Q systemd coreutils sudo
pacman-mirrors --get-branch
command -v systemctl systemd-analyze journalctl timedatectl sudo sudoedit date mktemp mv
از کجا بفهمم درست انجام شده؟

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

02

قدم بعدی

ساعت سیستم و چند نوبت بعدی رو ببین

ساعت اجرا رو صریحاً با UTC می‌نویسیم تا تغییر منطقهٔ زمانی میزبان یا ساعت تابستونی، نوبت موردنظر UTC رو جابه‌جا نکنه. قبل از ذخیرهٔ timer، وضعیت همگام‌سازی ساعت رو ببین و از خود systemd بخواه چند نوبت بعدی رو حساب کنه. درست‌بودن عبارت تقویمی فقط نحو اون رو ثابت می‌کنه؛ سلامت NTP، بیدارشدن سخت‌افزار یا برنامه رو ثابت نمی‌کنه.

سرویس زمان فعلی میزبان رو نگه دار. قرارگرفتن timer بعد از time-sync.target به‌تنهایی نشون نمی‌ده ساعت دقیق شده؛ وضعیت سرویس زمان رو هم باید باهاش تطبیق بدی. برای تمرین جبران نوبت ازدست‌رفته، ساعت میزبان رو جلو و عقب نبر و منطقهٔ زمانی سیستم رو عوض نکن.

bash

ترمینال میزبان آزمایشی با دسترسی مجاز

timedatectl status
date -u
systemd-analyze calendar --iterations=5 '*-*-* 3:00:00 UTC'
از کجا بفهمم درست انجام شده؟

عبارت نرمال‌شده و پنج نوبت بعدی UTC با زمان موردنظرت سازگارن. اگر ساعت همگام نیست، قبل از فعال‌کردن علتش رو پیدا کن.

03

قدم بعدی

فایل‌های یک کار تازه رو آماده کنیم

برای نمونه، اسکریپت و سرویس و timer مستقل می‌سازیم. اگر واحد یا پوشهٔ داده از قبل وجود داشته باشه، ادامه نمی‌دیم؛ پوشهٔ خصوصی‌ای که DynamicUser استفاده می‌کنه هم بررسی می‌شه. ساخت انحصاری فایل‌ها روی فایل یا پیوند موجود متوقف می‌شه. اگر رزرو فایل دوم یا سوم شکست بخوره، ممکنه فایل‌های خالی قبلی باقی مونده باشن؛ همان فایل‌ها رو بررسی کن و تا رفع مشکل timer رو فعال نکن.

سه محتوای بعدی رو در فایل‌های متناظر ویرایشگر بذار. پوشهٔ مشترک اسکریپت‌ها می‌تونه از قبل وجود داشته باشه، ولی فقط فایل‌های نام‌برده به این آموزش مربوط می‌شن. فایل واحدِ بسته‌ها یا فایل کار دیگری رو تغییر نده. برای نصب فایل‌ها دسترسی مدیر لازم داریم، اما خود کار با هویت موقت و بدون دسترسی مدیر اجرا می‌شه.

bash

ترمینال میزبان آزمایشی با دسترسی مجاز

test "$(systemctl show -p LoadState --value 'academy-daily-marker.service')" = not-found || exit 1
test "$(systemctl show -p LoadState --value 'academy-daily-marker.timer')" = not-found || exit 1
sudo test ! -e '/var/lib/academy-daily-marker' || exit 1
sudo test ! -e '/var/lib/private/academy-daily-marker' || exit 1
sudo install -d -m 0755 /usr/local/libexec
sudo sh -c 'set -euC; : > "$1"; : > "$2"; : > "$3"' sh '/usr/local/libexec/academy-daily-marker.sh' '/etc/systemd/system/academy-daily-marker.service' '/etc/systemd/system/academy-daily-marker.timer' || exit 1
sudo chmod 0644 '/usr/local/libexec/academy-daily-marker.sh' '/etc/systemd/system/academy-daily-marker.service' '/etc/systemd/system/academy-daily-marker.timer'
sudoedit '/usr/local/libexec/academy-daily-marker.sh' '/etc/systemd/system/academy-daily-marker.service' '/etc/systemd/system/academy-daily-marker.timer'
از کجا بفهمم درست انجام شده؟

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

کار تکرارپذیر بنویسیم و پایانش رو با فایل نهایی ثبت کنیم

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

این روش فقط تکرارپذیری یک خروجی کوچک محلی رو نشون می‌ده. تغییر نام فایل، فراخوانی API یا تغییر دیتابیس رو دقیقاً یک‌بار نمی‌کنه و تضمین ذخیرهٔ پایدار روی دیسک هم نیست. برنامهٔ واقعی به تراکنش، شناسهٔ جلوگیری از تکرار یا ثبت پیشرفت قابل‌بازیابی خودش نیاز داره. این اسکریپت رو فقط از راه همین سرویس اجرا کن؛ اجرای مستقیمِ هم‌زمان، کنترل systemd رو دور می‌زنه.

sh · /usr/local/libexec/academy-daily-marker.sh

محتوای فایل؛ در ترمینال اجرا نکن

#!/bin/sh
set -eu
umask 077
: "${STATE_DIRECTORY:?Start this job through its systemd service}"
day=$(date -u +%F)
report="$STATE_DIRECTORY/$day.txt"
if test -f "$report"; then
    printf 'ALREADY_DONE %s\n' "$day"
    exit 0
fi
tmp=$(mktemp "$STATE_DIRECTORY/.report.XXXXXX")
trap 'rm -f -- "$tmp"' EXIT HUP INT TERM
printf 'academy daily marker for UTC day %s\n' "$day" > "$tmp"
mv -- "$tmp" "$report"
trap - EXIT HUP INT TERM
printf 'COMPLETED %s\n' "$day"
همهٔ آموزش‌های آکادمی ↗