درک یونیتها و فایلهای یونیت 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 | .slice | Sliceهای 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 به شما کنترل میدهد که سرویسها کِی شروع شوند و چگونه دیباگشان کنید.




