لینوکس

درک یونیت‌ها و فایل‌های یونیت systemd

مقدمه

توزیع‌های لینوکس به‌طور گسترده از سیستم init یعنی systemd برای مدیریت سرویس‌ها، دستگاه‌ها، مونت‌ها و حالت‌های بوت استفاده می‌کنند. در systemd، یونیت (Unit) هر منبعی است که سیستم می‌داند چگونه روی آن عمل و آن را مدیریت کند. یونیت‌ها با فایل‌های پیکربندی‌ای به نام فایل‌های یونیت تعریف می‌شوند. این راهنما توضیح می‌دهد یونیت‌ها و فایل‌های یونیت systemd چیستند، کجا قرار دارند، چگونه آن‌ها را بنویسید و سفارشی کنید و چگونه با systemctl، journalctl و systemd-analyze آن‌ها را مدیریت و عیب‌یابی کنید. برای کنترل روزمره سرویس‌ها، «نحوه استفاده از systemctl برای مدیریت سرویس‌ها و یونیت‌های systemd» در پارمین کلود را ببینید.

نکات کلیدی

  • یک یونیت systemd یک منبع مدیریت‌شده است (سرویس، سوکت، مونت، تایمر و…)؛ فایل یونیت فایل پیکربندی‌ای است که آن یونیت را تعریف می‌کند.
  • فایل‌های یونیت سفارشی و Override را زیر /etc/systemd/system/ قرار دهید تا توسط پکیج‌ها بازنویسی نشوند و بر /lib/systemd/system/ (یا /usr/lib/systemd/system/) اولویت داشته باشند.
  • از فایل‌های Drop-In در /etc/systemd/system/<unit>.d/*.conf برای بازنویسی دایرکتیوهای خاص استفاده کنید؛ دایرکتیوهای exec (مثل ExecStart=) را قبل از تعریف مجدد پاک کنید.
  • فعال‌سازی سوکت (Socket Activation) از یک یونیت .socket برای ساخت سوکت و یک یونیت .service که در لحظه نیاز شروع می‌شود استفاده می‌کند؛ پارالل‌سازی بوت و شروع در لحظه را بهبود می‌بخشد.
  • وابستگی‌ها: از Wants= برای وابستگی‌های اختیاری و Requires= برای وابستگی‌های الزامی استفاده کنید؛ از After=/Before= برای ترتیب استفاده کنید. BindsTo= «توقف با توقف دیگری» را اضافه می‌کند.
  • systemctl enable فعال‌سازی هنگام بوت را تنظیم می‌کند (Symlink)؛ systemctl start یونیت را الان شروع می‌کند. systemctl stop آن را متوقف اما Symlinkهای enable را حذف نمی‌کند.
  • بعد از هر تغییر فایل یونیت یا Drop-In، قبل از شروع، ری‌استارت یا فعال‌سازی یونیت، systemctl daemon-reload را اجرا کنید.
  • از journalctl -u <unit> و journalctl -u <unit> -f برای مشاهده و دنبال کردن لاگ‌ها استفاده کنید؛ از systemd-analyze و systemd-analyze blame / critical-chain برای تشخیص عملکرد بوت و ترتیب شروع یونیت‌ها بهره ببرید.

پیش‌نیازها

  • یک سیستم لینوکسی با systemd (اوبونتو، دبیان، فدورا، CentOS Stream یا آرچ لینوکس)
  • یک کاربر غیر root با دسترسی sudo
  • آشنایی پایه با ترمینال و دستورات لینوکس

اگر سرور جدیدی راه‌اندازی می‌کنید، اول «راه‌اندازی اولیه سرور با اوبونتو» در پارمین کلود را ببینید.

systemd چیست و چرا سیستم‌های init سنتی را جایگزین کرد

مشکل اصلی SysVinit توالی‌بودن بود: هر سرویس باید منتظر اتمام قبلی می‌ماند تا شروع شود. اسکریپت سرویس SysVinit اغلب ۵۰ تا ۱۰۰ خط شل بود که منطق start، stop، reload و status را دستی مدیریت می‌کرد؛ بدون استانداردی برای تعریف وابستگی یا بازیابی از خطا.

systemd آن مدل را جایگزین می‌کند. فایل‌های یونیت اعلانی (Declarative) را می‌خواند، کل گراف وابستگی را قبل از شروع هر چیزی حل می‌کند و یونیت‌ها را هرجا که ترتیب اجازه دهد، به‌صورت موازی فعال می‌کند. سرویسی که قبلاً ۳۰ ثانیه ترتیبی برای رسیدن به حالت اجرا لازم داشت، می‌تواند وقتی وابستگی‌های مستقلش هم‌زمان شروع شوند، زیر ۱۰ ثانیه به آن برسد.

فراتر از سرعت، systemd فراهم می‌کند: لاگینگ یکپارچه از طریق ژورنال (بدون نیاز به پیکربندی جداگانه syslog)، فعال‌سازی سوکت و مسیر تا سرویس‌ها فقط در لحظه نیاز شروع شوند، ردیابی منابع مبتنی بر cgroup تا هر پروسه‌ای که سرویس تولید کرده حساب شود و امن‌سازی Sandbox از طریق دایرکتیوها در خود فایل یونیت.

systemd سیستم init روی اوبونتو، دبیان، RHEL، فدورا، CentOS Stream، آرچ لینوکس و بیشتر توزیع‌های دیگر لینوکس فعلی است.

یونیت systemd چیست

اگر systemctl status nginx را اجرا کرده باشید، خروجی‌ای که دیدید—وضعیت سرویس، PID، مصرف حافظه، خطوط لاگ اخیر و فعال بودنش هنگام بوت—یک یونیت را توصیف می‌کند. یونیت شیئی است که systemd ردیابی و مدیریت می‌کند. فایل یونیت فایل پیکربندی روی دیسک است که به systemd می‌گوید یونیت چیست، چگونه شروع شود، به چه چیزی وابسته است و کِی باید اجرا شود.

یونیت‌ها به سرویس‌ها محدود نیستند. systemd از همان مدل برای مدیریت سوکت‌های شبکه، نقاط مونت فایل‌سیستم، دستگاه‌های Swap، دستگاه‌های سخت‌افزاری، وظایف زمان‌بندی‌شده و ایستگاه‌های بررسی وضعیت سیستم استفاده می‌کند. هر نوع، پسوند فایل یونیت خودش و بخش خودش در فایل یونیت برای پیکربندی اختصاصی-نوع را دارد.

ایده‌هایی که سیستم‌های init دیگر ممکن است در یک اسکریپت بگنجانند، اغلب در systemd به چند یونیت تقسیم می‌شوند (مثلاً یک یونیت .socket و یک یونیت .service). آن جداسازی امکان فعال‌سازی مبتنی بر سوکت، شروع موازی و سفارشی‌سازی آسان‌تر از طریق Overrideهای Drop-In را می‌دهد. قابلیت‌هایی که یونیت‌ها فراهم می‌کنند شامل:

  • فعال‌سازی مبتنی بر سوکت: سوکت‌ها می‌توانند در اوایل فرایند بوت ساخته شوند؛ سرویس مرتبط فقط وقتی سوکت اولین‌بار استفاده شود شروع می‌شود؛ که پارالل‌سازی و شروع در لحظه را بهبود می‌بخشد.
  • امن‌سازی: دایرکتیوهایی مانند NoNewPrivileges=، ProtectSystem= و PrivateTmp= آنچه سرویس می‌تواند به آن دسترسی داشته باشد را محدود می‌کنند.
  • Overrideهای Drop-In: می‌توانید رفتار یونیت را با افزودن فایل‌هایی زیر /etc/systemd/system/<unit>.d/ بدون ویرایش فایل‌های یونیت فروشنده بازنویسی یا گسترش دهید.

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

فایل‌های یونیت systemd کجا قرار دارند: مسیرهای بارگذاری و اولویت

فایل‌های یونیت از چند دایرکتوری خوانده می‌شوند. هنگام بارگذاری یک یونیت، systemd این مسیرها را به‌ترتیب اولویت ثابتی جستجو و اولین فایل یونیت کامل (با بالاترین اولویت) را که پیدا کند به‌عنوان تعریف اصلی انتخاب می‌کند. سپس هر قطعه Drop-In منطبق از دایرکتوری‌های *.d/ متناظر را—باز هم به ترتیب اولویت—اعمال می‌کند. دانستن این ترتیب به شما می‌گوید فایل‌های یونیت سفارشی یا تغییرکرده را کجا بگذارید تا توسط به‌روزرسانی پکیج‌ها بازنویسی نشوند و تغییرات‌تان اثر بگذارد.

دایرکتوریاولویت (۱ = بالاترین)چه زمانی استفاده شود
/etc/systemd/system/۱فایل‌های یونیت سفارشی و Overrideها. از ریبوت‌ها جان سالم به در می‌برد و توسط پکیج‌ها بازنویسی نمی‌شود. برای سرویس‌های جدید یا جایگزینی کامل یونیت فروشنده استفاده کنید.
/run/systemd/system/۲یونیت‌های فقط-زمان-اجرایی. بالاترین اولویت بعد از /etc. تغییرات با ریبوت از بین می‌روند. توسط systemd و نصب‌کننده‌ها برای Overrideهای موقت استفاده می‌شوند.
/lib/systemd/system/ (یا /usr/lib/systemd/system/)۳یونیت‌های ارائه‌شده توسط فروشنده و پکیج‌ها. ویرایش نکنید؛ به‌جایش از /etc/systemd/system/ یا فایل‌های Drop-In برای Override استفاده کنید.

روی برخی توزیع‌ها مسیر فروشنده /usr/lib/systemd/system/ به‌جای /lib/systemd/system/ است. هر دو نسبت به /etc و /run اولویت یکسانی دارند.

فایل‌های یونیت سفارشی و دایرکتوری‌های Drop-In را زیر /etc/systemd/system/ قرار دهید تا به‌روزرسانی پکیج‌ها آن‌ها را بازنویسی نکند و پیکربندی‌تان بین ریبوت‌ها باقی بماند.

کالبدشناسی یک فایل یونیت systemd

فایل‌های یونیت، فایل‌های متنی ساده به سبک INI هستند. ساختار در بخش‌هایی سازمان‌دهی شده؛ هر کدام با نام بخش در براکت مربع شروع می‌شود؛ مثلاً [Unit]، [Service]، [Install]. نام بخش‌ها به بزرگی و کوچکی حروف حساس‌اند. بین هدرهای بخش، دایرکتیوها از فرمت کلید-مقدار با علامت مساوی استفاده می‌کنند. در فایل‌های Drop-In، یک دایرکتیو را می‌توان با تخصیص مقدار خالی قبل از تعریف مجدد، پاک کرد. برای الگوی کامل و مثال کاربردی، بخش «Overrideهای Drop-In» را در پایین ببینید.

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

[Unit]
Description=My startup script
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/myscript.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
  • [Unit] متادیتا و ترتیب را نگه می‌دارد. After=network.target یعنی این یونیت بعد از بالا آمدن شبکه شروع می‌شود؛ اما آن را الزامی نمی‌کند.
  • [Service] تعریف می‌کند چه چیزی اجرا شود. Type=oneshot یعنی systemd تا خروج اسکریپت منتظر می‌ماند تا یونیت را شروع‌شده تلقی کند. RemainAfterExit=yes یعنی یونیت بعد از پایان اسکریپت در حالت «active» می‌ماند.
  • [Install] رفتار بوت را تعریف می‌کند. WantedBy=multi-user.target یعنی systemctl enable یک Symlink می‌سازد که این یونیت را به توالی بوت معمولی چندکاربره می‌کشد.

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

systemd چندین شکل بولی را می‌پذیرد (1/yes/on/true و 0/no/off/false) و مقادیر زمانی را منعطف پارس می‌کند (اعداد بدون واحد یعنی ثانیه). بخش‌هایی که با X- شروع می‌شوند توسط systemd نادیده گرفته می‌شوند و می‌توانند برای ابزارها یا مستندسازی استفاده شوند.

دایرکتیوهای بخش [Unit]

بخش [Unit] متادیتا و روابط با یونیت‌های دیگر را نگه می‌دارد. دایرکتیوهای رایج:

  • Description=: توضیح کوتاه و قابل‌خواندن-انسانی که توسط systemctl status و ابزارهای مشابه نمایش داده می‌شود.
  • Documentation=: URIهای صفحات man یا مستندات؛ توسط systemctl status افشا می‌شود.
  • Requires=: یونیت‌های فهرست‌شده باید با این یونیت فعال شوند؛ اگر شکست بخورند، این یونیت شکست می‌خورد. به‌طور پیش‌فرض ترتیب‌بندی ندارد؛ با After= استفاده کنید.
  • Wants=: systemd سعی می‌کند یونیت‌های فهرست‌شده را وقتی این یونیت شروع می‌شود، راه بیندازد. اگر شکست بخورند یا غایب باشند، این یونیت همچنان اجرا می‌شود. برای بیشتر وابستگی‌های اختیاری ترجیح داده می‌شود.
  • BindsTo=: مثل Requires=؛ اما این یونیت وقتی یونیت فهرست‌شده متوقف شود، متوقف می‌شود.
  • After= / Before=: فقط ترتیب‌بندی. After= یعنی «بعد از این یونیت‌ها شروع شو»؛ Before= یعنی «این یونیت‌ها بعد از این یکی شروع می‌شوند». خودشان به‌تنهایی وابستگی ایجاد نمی‌کنند.
  • Conflicts=: یونیت‌های فهرست‌شده نمی‌توانند هم‌زمان اجرا شوند؛ شروع این یونیت آن‌ها را متوقف می‌کند.
  • Condition...= / Assert...=: دایرکتیوهای Condition در صورت برآورده‌نشدن، یونیت را رد می‌کنند؛ دایرکتیوهای Assert در صورت برآورده‌نشدن، فعال‌سازی را شکست می‌دهند.

دایرکتیوهای بخش [Install]

بخش اختیاری [Install] تعریف می‌کند هنگام فعال یا غیرفعال کردن یونیت چه اتفاقی می‌افتد. فعال‌سازی یونیت معمولاً یک Symlink می‌سازد تا یونیت هنگام بوت کشیده شود (مثلاً توسط یک Target).

  • WantedBy=: وقتی systemctl enable <unit> را اجرا می‌کنید، دایرکتوری .wants زیر /etc/systemd/system برای Target فهرست‌شده ساخته می‌شود (مثلاً multi-user.target.wants) و Sylinkی به این یونیت آن‌جا قرار می‌گیرد. غیرفعال‌سازی Symlink را حذف می‌کند.
  • RequiredBy=: همان ایده WantedBy= اما وابستگی الزامی می‌سازد (.requires).
  • Also=: یونیت‌های اضافی برای فعال یا غیرفعال کردن همراه با این یکی.
  • Alias=: نام‌های اضافی که یونیت زیرشان می‌تواند فعال شود. به چندین ارائه‌دهنده اجازه می‌دهد نام مشترکی را بدون تداخل برآورده کنند.
  • DefaultInstance=: برای یونیت‌های قالب، شناسه Instance پیش‌فرضی را که وقتی هنگام فعال‌سازی Instance مشخصی ارائه نشده استفاده می‌شود، تنظیم می‌کند.

بخش‌های اختصاصی-نوع: [Service]، [Socket] و بقیه

هر نوع یونیت بخشی به نام خود نوع دارد (مثلاً [Service]، [Socket]، [Timer]). بخش [Service] بخشی است که برای مدیریت دیمن‌ها بیشتر ویرایش خواهید کرد.

بخش [Service]

Type= به systemd می‌گوید سرویس چگونه رفتار می‌کند تا بتواند پروسه اصلی را ردیابی و یونیت را درست «شروع‌شده» تلقی کند:

Typeمورد استفاده
simpleپیش‌فرض وقتی ExecStart= تنظیم شده. پروسه شروع‌شده توسط ExecStart= پروسه اصلی است. وقتی سرویس fork نمی‌کند یا از فعال‌سازی سوکت استفاده می‌کنید.
forkingپروسه fork شده و والد خارج می‌شود؛ فرزند دیمن واقعی است. PIDFile= را تنظیم کنید تا systemd فرزند را ردیابی کند.
oneshotوظیفه یک‌باره. systemd تا خروج پروسه منتظر می‌ماند تا یونیت را شروع‌شده تلقی کند. با RemainAfterExit=yes استفاده کنید اگر یونیت باید بعد از خروج دستور «active» بماند.
dbusسرویس روی D-Bus نامی می‌گیرد؛ systemd وقتی نام ظاهر شود ادامه می‌دهد. BusName= را روی آن نام تنظیم کنید.
notifyسرویس اعلان آمادگی (مثلاً sd_notify) وقتی شروع شد می‌فرستد. systemd منتظرش می‌ماند. برای سرویس‌هایی که می‌دانند کِی آماده‌اند.
execمثل simple؛ اما systemd سرویس را فقط بعد از اینکه پروسه ExecStart= با موفقیت execve() کرده شروع‌شده تلقی می‌کند. این خطاهای exec باینری اصلی را فوراً نمایان می‌کند؛ ترتیب دستورات ExecStartPre= را تغییر نمی‌دهد.
idleفقط بعد از ارسال همه کارهای فعال شروع می‌شود؛ عمدتاً برای سرویس‌های کنسول.
notify-reloadسرویس reload را پشتیبانی می‌کند؛ systemd بعد از ExecReload= اعلانی انتظار دارد.

دایرکتیوهای اجرا:

  • ExecStart=: مسیر کامل و آرگومان‌های پروسه اصلی. با - پیشوند بگذارید تا خروج غیرصفر بدون علامت‌گذاری شکست یونیت مجاز باشد. فقط یک ExecStart= به ازای یونیت (به‌جز در oneshot).
  • ExecStartPre= / ExecStartPost=: دستوراتی که قبل یا بعد از پروسه اصلی اجرا می‌شوند. چند خط مجاز است؛ با - پیشوند بگذارید تا شکست نادیده گرفته شود.
  • ExecReload=: دستور Reload کردن پیکربندی (مثلاً ارسال SIGHUP یا اجرای اسکریپت reload).
  • ExecStop=: دستور متوقف کردن سرویس؛ اگر تنظیم نشده، systemd پروسه اصلی را می‌کشد.
  • Restart=: کنترل می‌کند systemd کِی سرویس را خودکار ری‌استارت کند. مقادیر رایج:
    • no (پیش‌فرض): هرگز ری‌استارت نکن.
    • on-failure: اگر پروسه با کد خروج غیرصفر خارج شود، توسط سیگنال کشته شود یا به تایم‌اوت بخورد، ری‌استارت کن. برای سرویس‌های پروداکشن استفاده کنید.
    • always: فارغ از نحوه خروج پروسه ری‌استارت کن. برای سرویس‌هایی که هرگز نباید متوقف بمانند.
    • on-success: فقط اگر پروسه تمیز خارج شود (کد خروج ۰) ری‌استارت کن. به‌ندرت لازم.
    • on-abnormal: روی سیگنال‌ها و تایم‌اوت‌ها ری‌استارت کن اما نه روی خروج تمیز یا کدهای خروج شکست. از RestartSec= برای تنظیم زمان انتظار قبل از تلاش ری‌استارت استفاده کنید (مثلاً RestartSec=5).
  • TimeoutStartSec= / TimeoutStopSec= / TimeoutSec=: چقدر منتظر بمانیم قبل از تلقی شکست شروع/توقف یا کشتن پروسه.

لاگینگ: ارسال stdout و stderr به ژورنال دیباگ را ساده‌تر و همه‌چیز را یک‌جا نگه می‌دارد:

StandardOutput=journal
StandardError=journal

اختیاری: SyslogIdentifier= نام استفاده‌شده در ورودی‌های ژورنال برای این سرویس را تنظیم می‌کند.

درک انواع یونیت با جزئیات

یونیت‌ها بر اساس نوع دسته‌بندی می‌شوند؛ نوع با پسوند نام‌فایل مشخص می‌شود.

نوعپسوندهدف
Service.serviceدیمن‌ها و پروسه‌های طولانی‌مدت.
Socket.socketسوکت‌های شبکه یا IPC (و FIFOها) برای فعال‌سازی سوکت.
Target.targetنقاط هم‌گام‌سازی و گروه‌های یونیت؛ در توالی بوت استفاده می‌شوند.
Device.deviceدستگاه‌های افشاشده توسط udev/sysfs که systemd برای ترتیب‌بندی یا مونت مدیریت می‌کند.
Mount.mountنقطه مونت مدیریت‌شده توسط systemd (نام = مسیر با اسلش به‌جای خط تیره).
Automount.automountنقطه مونتی که در اولین دسترسی مونت می‌شود؛ با یونیت .mount جفت می‌شود.
Swap.swapفضای Swap (فایل یا دستگاه).
Path.pathفعال‌سازی مبتنی بر مسیر از طریق inotify؛ به‌طور پیش‌فرض یک .service منطبق را تریگر می‌کند.
Timer.timerفعال‌سازی مبتنی بر زمان (مثل cron)؛ یونیت مرتبط را تریگر می‌کند.
Slice.sliceSliceهای cgroup برای محدودیت‌های منابع (CPU، حافظه، I/O).
Scope.scopeگروه‌بندی پروسه‌های ایجادشده خارجی؛ توسط systemd از Bus/API ساخته می‌شوند، نه از فایل‌های یونیت.
Snapshot.snapshotاسنپ‌شات موقت وضعیت فعلی یونیت برای بازگشت (Rollback)؛ بین ریبوت‌ها باقی نمی‌ماند.

.slice: Sliceها به نودهای cgroup نگاشت می‌شوند و برای محدود کردن یا تخصیص CPU، حافظه و I/O استفاده می‌شوند. Sliceهای پیش‌فرض شامل user.slice، system.slice و machine.slice هستند. مورد استفاده: سقف‌گذاری مصرف منابع برای مجموعه‌ای از سرویس‌ها (مثلاً Sliceی برای کارهای Batch با MemoryMax= و CPUQuota=).

.scope: Scopeها توسط systemd از رویدادهای خارجی (مثلاً نشست‌های کاربر، مدیران کانتینر) ساخته می‌شوند. شما فایل‌های یونیت .scope نمی‌سازید؛ آن‌ها گروه‌هایی از پروسه‌هایی را نشان می‌دهند که خارج از systemd شروع شده‌اند. مورد استفاده: مشاهده و محدود کردن منابع یک نشست کاربر یا کانتینر.

.path: مسیرهای فایل‌سیستم را با inotify مانیتور می‌کند. وقتی مسیر مطابقت یابد (مثلاً فایل وجود دارد، دایرکتوری خالی نیست، فایل تغییر کرده)، systemd یونیت مرتبط را شروع می‌کند (پیش‌فرض: همان نام با .service). مورد استفاده: شروع سرویس بکاپ یا همگام‌سازی وقتی فایلی در دایرکتوری ظاهر می‌شود یا نوشته می‌شود.

مثال یونیت Path: اجرای اسکریپت پردازش هر وقت فایلی در /var/spool/incoming/ ظاهر شد:

/etc/systemd/system/incoming-processor.path:

[Unit]
Description=Watch /var/spool/incoming for new files

[Path]
PathExistsGlob=/var/spool/incoming/*
Unit=incoming-processor.service

[Install]
WantedBy=multi-user.target

/etc/systemd/system/incoming-processor.service:

[Unit]
Description=Process files in /var/spool/incoming

[Service]
Type=oneshot
ExecStart=/usr/local/bin/process-incoming.sh

یونیت Path را فعال کنید، نه سرویس را مستقیم:

sudo systemctl enable --now incoming-processor.path

.timer: فعال‌سازی یونیت دیگر (معمولاً .service) را روی تقویم (مثلاً OnCalendar=*-*-* 02:00:00) یا نسبت به بوت/شروع/فعال/غیرفعال بودن یونیت زمان‌بندی می‌کند. مورد استفاده: جایگزینی cron برای وظایف دوره‌ای؛ با لاگینگ سازگار و یکپارچگی وابستگی.

برای فهرست همه تایمرهای فعال و غیرفعال:

systemctl list-timers --all
NEXT                          LEFT      LAST                          PASSED   UNIT           ACTIVATES
Thu 2099-01-01 02:30:00 UTC   14h left  Wed 2099-12-31 02:30:01 UTC   9h ago   backup.timer   backup.service

تایم‌استمپ‌ها ساعت سیستم را در زمان دستور منعکس می‌کنند.

مثال یونیت Timer: اجرای اسکریپت بکاپ هر روز ساعت ۲:۳۰ صبح. اگر سیستم در آن زمان خاموش بود، بلافاصله در بوت بعدی اجرایش کن (Persistent=true):

/etc/systemd/system/backup.timer:

[Unit]
Description=Daily backup timer

[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true

[Install]
WantedBy=timers.target

/etc/systemd/system/backup.service:

[Unit]
Description=Daily backup job

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh

تایمر را فعال کنید (نه سرویس را؛ تایمر آن را فعال می‌کند):

sudo systemctl enable --now backup.timer

.automount: نقطه مونتی را تعریف می‌کند که در اولین دسترسی خودکار مونت می‌شود. باید یونیت .mount منطبق داشته باشد. مورد استفاده: مونت-تنبل (Lazy) فضای ذخیره‌سازی شبکه یا قابل‌حمل تا مونت فقط وقتی اتفاق بیفتد که چیزی به مسیر دسترسی داشته باشد.

فعال‌سازی سوکت (مثال کاربردی)

فعال‌سازی سوکت «گوش دادن روی سوکت» را از «اجرای سرویس» جدا می‌کند. systemd سوکت(ها) را اوایل می‌سازد؛ سرویس فقط وقتی سوکت اتصالی دریافت کند (یا اولین Datagram) شروع می‌شود. این پارالل‌سازی بوت را بهبود و شروع در لحظه را ممکن می‌کند تا سرویس فقط وقتی نیاز است اجرا شود.

مثال: یک سوکت TCP روی پورت ۲۰۰۰؛ یک Instance سرویس به ازای هر اتصال شروع و File Descriptor اتصال را از systemd دریافت می‌کند.

اگر socat موجود نیست نصبش کنید:

# دبیان / اوبونتو
sudo apt install socat

# فدورا / RHEL / CentOS Stream
sudo dnf install socat

# آرچ لینوکس
sudo pacman -S socat

/etc/systemd/system/echo.socket:

[Unit]
Description=Echo socket for socket activation

[Socket]
ListenStream=2000
Accept=yes

[Install]
WantedBy=sockets.target

/etc/systemd/system/echo@.service (قالب: systemd فی اتصال fd را به‌عنوان fd 3 به هر Instance پاس می‌دهد):

یونیت سرویس باید قالب باشد (نام شامل @) وقتی Accept=yes تنظیم شده. استفاده از نام سرویس غیر-قالب با Accept=yes باعث فعال‌سازی شکست‌خورده می‌شود.

[Unit]
Description=Echo service instance (socket-activated)

[Service]
Type=simple
ExecStart=/usr/bin/socat FD:3 STDIO
StandardInput=socket
StandardError=journal

با Accept=yes، systemd هر اتصال را می‌پذیرد و Instanceای از echo@.service را شروع می‌کند؛ و اتصال را به‌عنوان File Descriptor شماره ۳ پاس می‌دهد. socat FD:3 STDIO آن اتصال را به stdin/stdout پروسه پل می‌زند (رفتار echo). یونیت سوکت هنگام بوت یا با اجرای systemctl start echo.socket شروع می‌شود؛ هیچ سرویسی تا اولین کلاینت به پورت ۲۰۰۰ وصل نشود اجرا نمی‌شود.

فقط سوکت را فعال و شروع کنید؛ Instanceهای سرویس به ازای هر اتصال خودکار شروع می‌شوند:

sudo systemctl daemon-reload
sudo systemctl enable echo.socket
sudo systemctl start echo.socket
# Instanceهای echo@.service وقتی کلاینت‌ها به پورت 2000 وصل شوند خودکار شروع می‌شوند

برای تأیید: echo hello | nc localhost 2000 (باید hello را پس بگیرید). با systemctl status echo.socket چک کنید، Instanceها را با systemctl status 'echo@*.service' فهرست کنید و لاگ‌های یک Instance خاص را با journalctl -u echo@<instance>.service ببینید.

چرا مهم است: سوکت‌ها می‌توانند در اوایل توالی بوت به‌صورت موازی ساخته شوند؛ دیمن‌ها فقط در لحظه نیاز شروع می‌شوند؛ که زمان بوت و مصرف منابع بیکار را کاهش می‌دهد. این تفاوت کلیدی از سیستم‌های init سنتی است که در آن‌ها خود دیمن باید قبل از پذیرش اتصالات، سوکت را می‌ساخت و bind می‌کرد.

فایل‌های یونیت قالب و Instanceها

فایل‌های یونیت قالب از @ در نام استفاده می‌کنند (مثلاً example@.service) و می‌توانند چندین Instance بسازند (مثلاً example@8080.service، example@8081.service). Instanceها اغلب به‌صورت Symlink به قالب ساخته می‌شوند. در فایل یونیت، Specifierها در زمان اجرا جایگزین می‌شوند: %i نام Instance است (بخش بین @ و .)، %n نام کامل یونیت، %p پیشوند قبل از @. از %i برای رفتار خاص-پورت یا خاص-کانفیگ استفاده کنید (مثلاً ExecStart=/usr/bin/app --port %i). برای فهرست کامل Specifierها man systemd.unit را ببینید.

ترتیب‌بندی وابستگی: Wants، Requires، After، Before و BindsTo

دایرکتیوهای وابستگی کنترل می‌کنند کدام یونیت‌ها با هم شروع یا متوقف می‌شوند و به چه ترتیبی. دایرکتیوهای ترتیب‌بندی (After=، Before=) خودشان به‌تنهایی باعث شروع یونیت‌ها نمی‌شوند؛ آن‌ها را با Wants= یا Requires= ترکیب کنید.

دایرکتیواثراگر وابسته شکست بخورد یا متوقف شود
Wants=این یونیت‌ها را وقتی این یونیت شروع می‌شود راه بینداز. وابستگی نرم.این یونیت همچنان اجرا می‌شود.
Requires=این یونیت‌ها باید با این یونیت شروع شوند. وابستگی سخت.این یونیت در فعال‌سازی شکست می‌خورد.
BindsTo=مثل Requires=، به‌علاوه: وقتی یونیت فهرست‌شده متوقف شود، این یونیت متوقف می‌شود.این یونیت متوقف می‌شود.
After=این یونیت را بعد از یونیت‌های فهرست‌شده شروع کن (فقط ترتیب).بدون وابستگی؛ با Wants/Requires استفاده کنید.
Before=یونیت‌های فهرست‌شده بعد از این یونیت شروع می‌شوند (فقط ترتیب).بدون وابستگی.
Conflicts=این یونیت‌ها نمی‌توانند با این یونیت اجرا شوند.شروع این یونیت آن‌ها را متوقف می‌کند؛ شروع آن‌ها این یونیت را متوقف می‌کند.

مثال: یک وب‌اپ ممکن است Want= nginx و After= nginx داشته باشد تا nginx اول شروع شود؛ اما اپ همچنان شروع می‌شود اگر nginx غایب یا شکست‌خورده باشد. کلاینت دیتابیسی که حتماً باید دیتابیس داشته باشد، می‌تواند از Requires= و After= استفاده کند تا DB اول شروع و کلاینت در صورت شروع‌نشدن DB شکست بخورد.

مدیریت یونیت‌ها با systemctl

از systemctl برای شروع، توقف، فعال‌سازی، غیرفعال‌سازی و بازرسی یونیت‌ها استفاده کنید. عملیات‌های رایج:

  • شروع/توقف/ری‌استارت: systemctl start <unit>، systemctl stop <unit>، systemctl restart <unit>
  • فعال/غیرفعال کردن هنگام بوت: systemctl enable <unit> Symlinkهایی می‌سازد تا یونیت توسط Targetش (مثلاً multi-user.target) شروع شود؛ systemctl disable <unit> آن لینک‌ها را حذف می‌کند. Enable یونیت را الان شروع نمی‌کند؛ start آن را هنگام بوت فعال نمی‌کند.
  • فعال‌سازی و شروع در یک قدم: systemctl enable --now <unit> فعال می‌کند و فوراً شروعش می‌کند. systemctl disable --now <unit> غیرفعال می‌کند و متوقف‌اش می‌کند.
  • وضعیت: systemctl status <unit> وضعیت، خطوط لاگ اخیر و فعال بودن یونیت را نشان می‌دهد.
  • بازرسی فایل یونیت resolve شده: systemctl cat <unit> کل فایل یونیت را همان‌طور که systemd بارگذاری‌اش کرده چاپ می‌کند؛ شامل هر فایل Drop-In فعالِ به انتهای الصاق‌شده. از این استفاده کنید تا تأیید کنید کدام فایل بعد از ساخت یا تغییر یونیت اثر دارد.
  • بررسی فعال/غیرفعال بودن برای اسکریپت‌نویسی: systemctl is-active <unit> مقدار active یا inactive (کد خروج ۰ یا ۱) برمی‌گرداند؛ systemctl is-enabled <unit> مقدار enabled یا disabled برمی‌گرداند. هر دو مناسب استفاده در اسکریپت‌ها هستند.
  • Mask و unmask: systemctl mask <unit> با Symlink کردن به /dev/null جلوی شروع همیشگی یونیت را می‌گیرد. نمی‌تواند دستی شروع یا به‌عنوان وابستگی کشیده شود. systemctl unmask <unit> این را معکوس می‌کند. از Masking وقتی استفاده کنید که disable کافی نیست؛ مثلاً برای جلوگیری از فعال‌سازی مجدد سرویس متناقض توسط به‌روزرسانی پکیج.
  • Reload در مقابل restart: systemctl reload <unit> به پروسه در حال اجرا سیگنالی می‌فرستد تا پیکربندی‌اش را دوباره بخواند (نیازمند ExecReload= در فایل یونیت). systemctl restart <unit> پروسه را متوقف و شروع می‌کند. وقتی سرویس پشتیبانی می‌کند از reload استفاده کنید تا از قطع اتصالات فعال جلوگیری شود.

نمونه خروجی وضعیت:

● nginx.service - A high performance web server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled)
     Active: active (running) since Mon 2099-01-01 14:32:00 UTC; 2h ago
   Main PID: 1234 (nginx)
      Tasks: 5
     Memory: 12.5M
        CPU: 234ms

برای تأیید اینکه systemd بعد از هر تغییری از فایل یونیت به‌روزشده شما استفاده می‌کند:

systemctl cat myapp.service

خروجی مسیر فایل resolve شده را در بالا و هر Drop-In فعال را به انتهایش الصاق نشان می‌دهد. اگر تغییرات‌تان منعکس نشد، اول sudo systemctl daemon-reload را اجرا کنید.

ساخت فایل یونیت سرویس سفارشی از صفر

اینجا یک یونیت .service به سبک پروداکشن برای اپ فرضی‌ای که روی پورتی گوش می‌دهد، با کاربر غیر root اجرا می‌شود و از گزینه‌های امن‌سازی رایج استفاده می‌کند.

سناریو: باینری اپ در /opt/myapp/bin/myapp، کانفیگ در /etc/myapp/config.yaml، باید با کاربر myapp اجرا شود، در صورت شکست ری‌استارت و فایل‌سیستم و دسترسی‌های محدود داشته باشد.

قبل از ساخت فایل یونیت، کاربر سیستمی‌ای که سرویس با آن اجرا می‌شود را بسازید:

sudo useradd --system --no-create-home --shell /usr/sbin/nologin myapp

فلگ --system حساب سیستمی بدون شل ورود به‌طور پیش‌فرض می‌سازد. --no-create-home از دایرکتوری خانه می‌گذرد. --shell /usr/sbin/nologin تضمین می‌کند حساب قابل استفاده برای ورود تعاملی نباشد.

/etc/systemd/system/myapp.service را بسازید:

[Unit]
Description=MyApp daemon
Documentation=https://example.com/myapp/docs
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/bin/myapp --config /etc/myapp/config.yaml
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5
TimeoutStartSec=10
TimeoutStopSec=10

# لاگینگ
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp

# امن‌سازی
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
ReadWritePaths=/var/lib/myapp /etc/myapp
# حذف همه قابلیت‌ها؛ موارد خاص را اگر اپ نیاز دارد دوباره اضافه کنید
# مثلاً CapabilityBoundingSet=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=
AmbientCapabilities=
LockPersonality=yes
ProtectKernelTunables=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes
ProtectClock=yes
PrivateDevices=yes
ProtectHostname=yes
ProtectKernelModules=yes
ProtectProc=invisible
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
RestrictNamespaces=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
SystemCallFilter=@system-service
SystemCallFilter=~@privileged
SystemCallFilter=~@resources
UMask=0077

[Install]
WantedBy=multi-user.target
  • Type=simple: پروسه اصلی همان از ExecStart= است؛ بدون fork.
  • User= / Group=: اجرا با کاربر/گروه غیرممتاز.
  • WorkingDirectory=: دایرکتوری کاری پروسه.
  • ExecStart=: مسیر کامل و آرگومان‌ها؛ اگر اپ reload را پشتیبانی می‌کند از ExecReload= با $MAINPID استفاده کنید.
  • Restart=on-failure و RestartSec=: ری‌استارت خودکار با تأخیر کوتاه.
  • StandardOutput=journal / StandardError=journal: ارسال لاگ‌ها به ژورنال.
  • NoNewPrivileges=yes: از ارتقای دسترسی جلوگیری می‌کند.
  • ProtectSystem=strict: بیشتر سلسله‌مراتب فایل‌سیستم (شامل /etc، /usr، /boot، /var) را فقط-خواندنی می‌کند؛ از ReadWritePaths= (و دایرکتیوهای مرتبط) استفاده کنید تا نوشتن به دایرکتوری‌های لازم (مثلاً /var/lib/myapp) صریحاً مجاز شود.
  • PrivateTmp=yes: /tmp خصوصی برای سرویس.

systemd را ریلود، سپس سرویس را فعال و شروع کنید:

sudo systemctl daemon-reload
sudo systemctl enable --now myapp.service
sudo systemctl status myapp.service

تأیید کنید سرویس در حال اجرا و لاگینگ ژورنال کار می‌کند:

journalctl -u myapp.service -n 20

استفاده از فایل‌های Override برای سفارشی‌سازی رفتار یونیت

فایل‌های Drop-In به شما اجازه می‌دهند دایرکتیوهای خاصی از یک یونیت را بدون ویرایش فایل فروشنده در /lib/systemd/system/ بازنویسی یا گسترش دهید. آن‌ها زیر /etc/systemd/system/<unit>.d/ (مثلاً nginx.service.d/) با پسوند .conf قرار دارند. روند کار توصیه‌شده systemctl edit <unit> است؛ که دایرکتوری را می‌سازد و فایلی را باز می‌کند (پیش‌فرض: override.conf).

چه زمانی از Drop-In استفاده کنیم: فقط چند گزینه را تغییر دهید (مثلاً متغیرهای محیطی، Restart=، تایم‌اوت‌ها، خطوط exec). وقتی کل یونیت را جایگزین می‌کنید یا مجموعه تغییرات بزرگ است، از فایل یونیت کامل در /etc/systemd/system/ استفاده کنید.

پاک کردن و تعریف مجدد دایرکتیوهای exec: برای جایگزینی دستور شروع اصلی، اول باید پاکش کنید، سپس جدید را تنظیم کنید:

[Service]
ExecStart=
ExecStart=/usr/local/bin/nginx -c /etc/nginx/nginx-custom.conf

بدون ExecStart= خالی، بیشتر انواع سرویس با چند تعریف ExecStart= تمام می‌شدند؛ که نامعتبر است و باعث خطای systemd «more than one ExecStart= setting» می‌شود. تخصیص خالی، دستور اصلی را پاک می‌کند تا فقط جدید از Drop-In استفاده شود. همان الگو برای ExecStartPre=، ExecReload= و ExecStop= وقتی آن‌ها را Override می‌کنید اعمال می‌شود.

روند کار کامل:

sudo systemctl edit nginx.service

این ویرایشگر متن پیش‌فرض‌تان را ($EDITOR، معمولاً nano یا vi) با قالبی از پیش فرمت‌شده که نشان می‌دهد دایرکتیوهای‌تان را کجا بگذارید باز می‌کند. بعد از ذخیره، systemd نتیجه را در /etc/systemd/system/nginx.service.d/override.conf می‌نویسد. بعد systemctl cat nginx.service را اجرا کنید تا تأیید شود Override درست ادغام شده.

دایرکتیوهای‌تان را اضافه، ذخیره و خارج شوید. سپس:

sudo systemctl daemon-reload
sudo systemctl restart nginx.service

همیشه بعد از ساخت یا تغییر هر فایل یونیت یا Drop-In، systemctl daemon-reload را اجرا کنید؛ وگرنه systemd پیکربندی جدید را اعمال نمی‌کند.

مشاهده و تحلیل لاگ‌ها با journalctl

ژورنال systemd لاگ‌ها را از کرنل، systemd و سرویس‌هایی که از StandardOutput=journal / StandardError=journal استفاده می‌کنند ذخیره می‌کند. برای جزئیات کامل «نحوه استفاده از journalctl برای مشاهده و مدیریت لاگ‌های systemd» در پارمین کلود را ببینید؛ در پایین مفیدترین الگوها برای دیباگ یونیت آمده‌اند.

  • لاگ‌های یک یونیت: journalctl -u <unit> (مثلاً journalctl -u nginx.service).
  • بازه زمانی اخیر: journalctl -u nginx.service --since "1 hour ago" یا --since "today".
  • دنبال کردن زنده: journalctl -u nginx.service -f (follow).
  • فقط آخرین بوت: journalctl -b (بوت فعلی)؛ journalctl -b -1 برای بوت قبلی.
  • آخرین خطوط + دنبال کردن: journalctl -xe به انتهای ژورنال می‌پرد و متن کاتالوگ توضیحی برای ورودی‌هایی که دارند اضافه می‌کند. برای دنبال کردن خروجی زنده، از -f استفاده کنید.

نمونه خروجی برای یک یونیت:

Jun 04 14:32:00 host nginx[1234]: Starting nginx...
Jun 04 14:32:00 host systemd[1]: Started A high performance web server.
Jun 04 14:32:01 host nginx[1234]: nginx/1.18.0

از -o short-full برای تایم‌استمپ‌های کامل، -n 100 برای محدود کردن خطوط و -p err برای فیلتر بر اساس اولویت استفاده کنید.

خواندن الگوهای لاگ رایج:

وقتی یونیتی در شروع شکست می‌خورد، ژورنال معمولاً یکی از این الگوها را نشان می‌دهد:

دستور ExecStart= پیدا نشد یا permission denied:

myapp.service: Failed to execute command: No such file or directory
myapp.service: Failed at step EXEC spawning /opt/myapp/bin/myapp: No such file or directory

چک کنید مسیر باینری درست و قابل اجراست: ls -l /opt/myapp/bin/myapp.

سرویس شروع شد اما فوراً خارج شد:

myapp.service: Main process exited, code=exited, status=1/FAILURE
myapp.service: Failed with result 'exit-code'.

دستور ExecStart= را مستقیماً در شل‌تان اجرا کنید تا خروجی‌اش را ببینید. کد خروج و پیام‌های خطا در stdout/stderr ظاهر می‌شوند.

درخواست شروع بیش‌ازحد سریع تکرار شد (حلقه ری‌استارت):

myapp.service: Start request repeated too quickly.
myapp.service: Failed with result 'exit-code'.
systemd[1]: Failed to start MyApp daemon.

سرویس شکست می‌خورد و Restart=on-failure فوراً آن را برمی‌گرداند. RestartSec= را افزایش یا اول خرابی زیرین را رفع کنید. از journalctl -u myapp.service -n 50 برای دیدن کل توالی خروج استفاده کنید.

تشخیص عملکرد بوت با systemd-analyze

systemd-analyze به شما کمک می‌کند ببینید بوت چقدر طول کشید و کدام یونیت‌ها آن را به تأخیر انداختند.

کل زمان بوت:

systemd-analyze
Startup finished in 2.345s (kernel) + 8.901s (userspace) = 11.246s

زمان به ازای یونیت:

systemd-analyze blame
3.212s man-db.service
1.876s NetworkManager-wait-online.service
1.234s cloud-init.service
  892ms apt-daily.service
  ...

زنجیره بحرانی برای یک یونیت: systemd-analyze critical-chain nginx.service زنجیره یونیت‌هایی را که باید قبل از این یکی تمام می‌شدند و زمان‌هایشان را نشان می‌دهد:

The time when unit became active or started is printed after the "@" character.
multi-user.target @8.901s
└─nginx.service @8.234s +665ms
  └─network-online.target @8.230s
    └─NetworkManager-wait-online.service @6.354s +1.876s

تفسیر: NetworkManager-wait-online.service حدود ۱.۹ ثانیه گرفت و network-online.target را به تأخیر انداخت؛ که به نوبه خود nginx.service را به تأخیر انداخت. برای سریع‌تر کردن بوت می‌توانید یونیت‌های غیرضروری را غیرفعال یا relax کنید (مثلاً اگر قبل از شروع سرویس‌ها به «شبکه بالا آمده» نیاز ندارید، NetworkManager-wait-online را disable کنید) یا یونیت‌های کند را بهینه‌سازی کنید (مثلاً سنگین‌هایی مثل man-db.service را به تأخیر بیندازید یا mask کنید).

سوالات متداول

تفاوت یونیت systemd و فایل یونیت چیست؟

یونیت شیئی است که systemd مدیریت می‌کند: سرویس (در حال اجرا یا متوقف)، سوکت، تایمر و… فایل یونیت فایل پیکربندی است (مثلاً myservice.service) که تعریف می‌کند آن یونیت چگونه باید رفتار کند: چه چیزی اجرا شود، کِی شروع شود و چگونه با یونیت‌های دیگر مرتبط است. یک فایل یونیت می‌تواند یک یونیت را تعریف کند (یا با قالب‌ها، چندین یونیت Instance).

تفاوت Wants= و Requires= چیست؟

Wants= وابستگی نرم است: وقتی این یونیت شروع می‌شود، systemd سعی می‌کند یونیت‌های فهرست‌شده را شروع کند. اگر شکست بخورند یا غایب باشند، این یونیت همچنان فعال می‌شود. Requires= وابستگی سخت است: یونیت‌های فهرست‌شده باید با موفقیت شروع شوند؛ اگر هر کدام شکست بخورند، این یونیت در فعال‌سازی شکست می‌خورد. مگر اینکه یونیت واقعاً بدون دیگری نمی‌تواند کار کند، Wants= را ترجیح دهید.

فایل یونیت سفارشی را کجا بگذارم تا توسط به‌روزرسانی پکیج‌ها بازنویسی نشود؟

در /etc/systemd/system/ بگذارید. آن دایرکتوری بالاترین اولویت را دارد و برای یونیت‌های مدیر و خاص-سایت در نظر گرفته شده. مدیران پکیج یونیت‌ها را زیر /lib/systemd/system/ (یا /usr/lib/systemd/system/) نصب می‌کنند؛ که فایل‌های داخل /etc/systemd/system/ را بازنویسی نمی‌کنند.

بعد از ساخت یا تغییر فایل یونیت، چطور systemd را ریلود کنم؟

sudo systemctl daemon-reload را اجرا کنید. این همه فایل‌های یونیت و Drop-In را از دیسک دوباره بارگذاری می‌کند. سپس یونیت را در صورت نیاز شروع، ری‌استارت یا فعال کنید. بدون daemon-reload، systemd به استفاده از پیکربندی قدیمی در-حافظه ادامه می‌دهد.

فعال‌سازی سوکت چیست و کِی باید از آن استفاده کنم؟

فعال‌سازی سوکت یعنی systemd سوکت را می‌سازد و روی آن گوش می‌دهد (مثلاً TCP یا سوکت یونیکس)؛ پروسه سرویس فقط وقتی اتصالی (یا اولین Datagram) برسد شروع می‌شود. وقتی استفاده کنید که می‌خواهید سرویس در لحظه نیاز شروع شود، پارالل‌سازی بوت بهبود یابد (سوکت‌ها اوایل، سرویس‌ها بعدتر) یا سوکتِ از قبل bind-شده به دیمن تحویل شود تا خودش نیازی به bind نداشته باشد.

چطور جلوی شروع یونیتی هنگام بوت را بگیرم حتی اگر یونیت دیگری وابستگی Wants= روی آن داشته باشد؟

یونیت را غیرفعال کنید: sudo systemctl disable <unit>. این Symlinkهایی که آن را به توالی بوت می‌کشند حذف می‌کند. اگر یونیت دیگر فقط آن را بخواهد (نه Requires)، آن یونیت دیگر همچنان شروع می‌شود؛ یونیتِ خواسته‌شده صرفاً توسط وابستگی شروع نمی‌شود. اگر یونیت دیگر آن را Required کند، یونیتِ کننده ممکن است در فعال‌سازی شکست بخورد. برای جلوگیری کامل از شروع همیشگی یونیت، می‌توانید Maskش کنید: sudo systemctl mask <unit> (یونیت را با لینکی به /dev/null جایگزین می‌کند).

تفاوت systemctl stop و systemctl disable چیست؟

systemctl stop یونیت را فوراً متوقف اما اینکه هنگام بوت فعال است را تغییر نمی‌دهد. بعد از ریبوت، یونیت فعال‌شده همچنان شروع می‌شود. systemctl disable یونیت را از توالی بوت حذف (Symlinkهای زیر /etc/systemd/system/*.wants/ یا *.requires/ را حذف) اما الان متوقف‌اش نمی‌کند. از stop برای خاموش کردن در این بوت استفاده کنید؛ از disable برای جلوگیری از شروع در بوت‌های آینده (و اغلب هر دو: اول stop بعد disable).

چطور بفهمم چرا یونیتی در شروع شکست خورد؟

systemctl status <unit> را اجرا کنید تا وضعیت فعلی و چند خط لاگ آخر را ببینید. سپس journalctl -u <unit> -n 50 --no-pager (یا journalctl -u <unit> -xe) را برای خروجی لاگ بیشتر اجرا کنید. به دنبال دستورات ExecStart= شکست‌خورده، وابستگی‌های مفقود، بررسی‌های Condition یا Assert شکست‌خورده یا خطاهای مجوز بگردید. systemctl show <unit> --property=Result --property=ExecMainStatus می‌تواند نتیجه و کد خروج پروسه اصلی را نشان دهد.

نتیجه‌گیری

درک یونیت‌ها و فایل‌های یونیت systemd، محور مدیریت سرویس‌های لینوکس و توالی بوت است. فایل‌های یونیت از فرمت اعلانی به سبک INI استفاده می‌کنند تا وابستگی‌ها، اجرا و امن‌سازی را یک‌جا ببینید. نگه‌داشتن سفارشی‌سازی‌ها در /etc/systemd/system/ و استفاده از Overrideهای Drop-In، یونیت‌های فروشنده را دست‌نخورده و ارتقاها را قابل پیش‌بینی نگه می‌دارد. استفاده از فعال‌سازی سوکت، ترتیب‌بندی وابستگی و ژورنال با journalctl و systemd-analyze به شما کنترل می‌دهد که سرویس‌ها کِی شروع شوند و چگونه دیباگ‌شان کنید.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

همچنین ببینید
بستن
دکمه بازگشت به بالا