| SYSTEMD.SERVICE(5) | systemd.service | SYSTEMD.SERVICE(5) |
نام (NAME)
systemd.service - پیکربندی و تعاریف سرویسهای systemd
خلاصه دستور (SYNOPSIS)
service.service
توضیحات (DESCRIPTION)
یک فایل پیکربندی واحد که نام آن به ".service" ختم میشود، اطلاعات مربوط به فرآیندی را که توسط systemd کنترل و نظارت میشود، کدگذاری میکند.
این صفحه راهنما، گزینههای پیکربندی مخصوص این نوع واحد را فهرست میکند. برای گزینههای مشترک تمام فایلهای پیکربندی واحد، systemd.unit(5) را ببینید. موارد پیکربندی مشترک در بخشهای عمومی [Unit] و [Install] پیکربندی میشوند. گزینههای پیکربندی مخصوص سرویس در بخش [Service] پیکربندی میشوند.
گزینههای اضافی در systemd.exec(5) فهرست شدهاند، که محیط اجرایی را که دستورات در آن اجرا میشوند تعریف میکند، و در systemd.kill(5)، که نحوه خاتمه فرآیندهای سرویس را تعریف میکند، و در systemd.resource-control(5)، که تنظیمات کنترل منابع را برای فرآیندهای سرویس پیکربندی میکند.
اگر سازگاری با SysV init فعال باشد، systemd بهطور خودکار واحدهای سرویسی ایجاد میکند که اسکریپتهای SysV init را در بر میگیرند (نام سرویس همان نام اسکریپت خواهد بود، با افزودن پسوند ".service")؛ systemd-sysv-generator(8) را ببینید.
دستور systemd-run(1) امکان ایجاد واحدهای .service و .scope را بهطور پویا و گذرا از خط فرمان فراهم میکند.
الگوهای سرویس (SERVICE TEMPLATES)
امکانپذیر است که سرویسهای systemd یک آرگومان منفرد را از طریق نحو "service@argument.service" دریافت کنند. چنین سرویسهایی، سرویسهای «نمونهسازیشده» (instantiated) نامیده میشوند، در حالی که تعریف واحد بدون پارامتر argument یک «الگو» (template) نام دارد. برای نمونه میتوان به الگوی سرویس dhcpcd@.service اشاره کرد که یک واسط شبکه را به عنوان پارامتر میگیرد تا یک سرویس نمونهسازیشده ایجاد کند. در درون فایل سرویس، به این پارامتر یا «نام نمونه» میتوان با مشخصکنندههای %- دسترسی داشت. برای جزئیات، systemd.unit(5) را ببینید.
وابستگیهای خودکار (AUTOMATIC DEPENDENCIES)
وابستگیهای ضمنی (Implicit Dependencies)
وابستگیهای زیر بهطور ضمنی اضافه میشوند:
وابستگیهای ضمنی اضافی ممکن است در نتیجه پارامترهای اجرا و کنترل منابع، همانگونه که در systemd.exec(5) و systemd.resource-control(5) مستند شده است، اضافه شوند.
وابستگیهای پیشفرض (Default Dependencies)
وابستگیهای زیر اضافه میشوند مگر اینکه DefaultDependencies=no تنظیم شده باشد:
گزینهها (OPTIONS)
فایلهای واحد سرویس ممکن است شامل بخشهای [Unit] و [Install] باشند که در systemd.unit(5) شرح داده شدهاند.
فایلهای واحد سرویس باید شامل یک بخش [Service] باشند که حامل اطلاعات مربوط به سرویس و فرآیندی است که بر آن نظارت دارد. تعدادی از گزینههایی که ممکن است در این بخش استفاده شوند با سایر انواع واحد مشترک هستند. این گزینهها در systemd.exec(5)، systemd.kill(5) و systemd.resource-control(5) مستند شدهاند. گزینههای مخصوص بخش [Service] واحدهای سرویس موارد زیر هستند:
Type=
انتظار میرود فرآیندی که با ExecStart= پیکربندی شده است، فرآیند اصلی سرویس باشد. در این حالت، اگر فرآیند قابلیتهایی را به سایر فرآیندهای روی سیستم ارائه میدهد، کانالهای ارتباطی آن باید پیش از راهاندازی سرویس برقرار شوند (برای نمونه سوکتهای راهاندازیشده توسط systemd، از طریق فعالسازی سوکت)، زیرا مدیر سرویس بلافاصله پس از ایجاد فرآیند اصلی سرویس و پیش از اجرای باینری سرویس، به سراغ راهاندازی واحدهای بعدی میرود. توجه داشته باشید که این بدان معناست که خطوط فرمان systemctl start برای سرویسهای simple موفقیت را گزارش میدهند، حتی اگر باینری سرویس نتواند با موفقیت فراخوانی شود (برای مثال به این دلیل که User= انتخابشده وجود ندارد، یا باینری سرویس مفقود است).
انتظار میرود فرآیندی که با ExecStart= پیکربندی شده است، به عنوان بخشی از راهاندازی خود fork() را فراخوانی کند. انتظار میرود پس از اتمام راهاندازی و برقراری تمام کانالهای ارتباطی، فرآیند والد خارج شود. فرآیند فرزند به عنوان فرآیند اصلی سرویس به کار خود ادامه میدهد و مدیر سرویس هنگامی که فرآیند والد خارج شد واحد را شروعشده تلقی میکند. این رفتار سنتی سرویسهای UNIX است. در صورت استفاده از این تنظیم، توصیه میشود از گزینه PIDFile= نیز استفاده کنید تا systemd بتواند فرآیند اصلی سرویس را بهطور قابل اعتماد شناسایی کند. مدیر سرویس پس از خروج فرآیند والد، شروع واحدهای بعدی را آغاز خواهد کرد.
واحدهای سرویسی که این گزینه برای آنها پیکربندی شده است بهطور ضمنی وابستگیهایی به واحد dbus.socket به دست میآورند. یک واحد سرویس از این نوع تا زمانی که نام گذرگاه مشخصشده تصاحب نشود در وضعیت در حال فعالسازی (activating) در نظر گرفته میشود. تا زمانی که نام گذرگاه در دست باشد، فعالشده (activated) محسوب میشود. به محض اینکه نام گذرگاه رها شود، سرویس دیگر به عنوان کارکردی در نظر گرفته نمیشود که پیامد آن تلاش مدیر سرویس برای پایان دادن به فرآیندهای باقیمانده متعلق به سرویس است. بنابراین سرویسهایی که به عنوان بخشی از منطق خاموش شدن خود نام گذرگاه خود را رها میکنند، باید برای دریافت سیگنال SIGTERM (یا هر سیگنالی که در KillSignal= پیکربندی شده است) در نتیجه این امر آماده باشند.
اگر سرویس از بارگذاری مجدد (reloading) پشتیبانی میکند و از یک سیگنال برای شروع بارگذاری مجدد استفاده میکند، استفاده از notify-reload در عوض توصیه میشود.
هنگام آغاز فرآیند بارگذاری مجدد، انتظار میرود سرویس با یک پیام اعلان از طریق sd_notify(3) پاسخ دهد که شامل فیلد "RELOADING=1" به همراه "MONOTONIC_USEC=" تنظیمشده روی زمان یکنواخت کنونی (یعنی CLOCK_MONOTONIC در clock_gettime(2)) به میکروثانیه، قالببندیشده به عنوان یک رشته دهدهی باشد. پس از تکمیل بارگذاری مجدد، پیام اعلان دیگری باید ارسال شود که حاوی "READY=1" باشد. استفاده از این نوع سرویس و پیادهسازی این پروتکل بارگذاری مجدد، جایگزینی کارآمد برای ارائه دستور ExecReload= جهت بارگذاری مجدد پیکربندی سرویس است.
سیگنالی که باید ارسال شود را میتوان از طریق ReloadSignal= تغییر داد، به زیر مراجعه کنید.
توصیه میشود از Type=exec برای سرویسهای با اجرای طولانی استفاده شود، زیرا تضمین میکند که خطاهای راهاندازی فرآیند (مانند خطاهایی چون نبود فایل اجرایی سرویس، یا مفقود بودن کاربر) به درستی ردیابی شوند. با این حال، از آنجا که این نوع سرویس خرابیهای درون کد راهاندازی خود سرویس را منتشر نمیکند (برخلاف خرابیها در مراحل مقدماتی که مدیر سرویس قبل از execve() اجرا میکند) و اجازه ترتیببندی سایر واحدها را بر اساس تکمیل مقداردهی اولیه کد خود سرویس نمیدهد (که به عنوان مثال زمانی مفید است که کلاینتها نیاز دارند از طریق نوعی از IPC به سرویس متصل شوند، و کانال IPC تنها توسط خود سرویس ایجاد میشود — در مقایسه با انجام این کار از قبل از طریق فعالسازی سوکت یا گذرگاه یا موارد مشابه)، ممکن است برای بسیاری از موارد کافی نباشد. در این صورت، notify، notify-reload، یا dbus (مورد اخیر فقط در صورتی که سرویس یک واسط D-Bus ارائه دهد) گزینههای ترجیحی هستند زیرا به کد برنامه سرویس اجازه میدهند دقیقاً زمان شروع موفقیتآمیز سرویس و زمان ادامه کار با واحدهای بعدی را زمانبندی کند. انواع سرویس notify/notify-reload نیازمند پشتیبانی صریح در پایهکد سرویس هستند (زیرا sd_notify() یا یک API معادل باید توسط سرویس در زمان مناسب فراخوانی شود) — اگر پشتیبانی نشود، forking یک جایگزین است: از پروتکل سنتی و سنگین راهاندازی سرویسهای UNIX پشتیبانی میکند. توجه داشته باشید که استفاده از هر نوع دیگری به جز simple احتمالاً فرآیند بوت را به تأخیر میاندازد، زیرا مدیر سرویس باید حداقل منتظر بماند تا بخشی از مقداردهی اولیه سرویس تکمیل شود. (همچنین توجه داشته باشید که معمولاً استفاده از idle یا oneshot برای سرویسهای با اجرای طولانی توصیه نمیشود.)
توجه داشته باشید که تنظیمات مختلف سرویس (مانند User=، Group= از طریق libc NSS) ممکن است در هنگام استفاده منجر به فراخوانیهای IPC مسدودکننده «پنهان» به سایر سرویسها شود. گاهی اوقات ممکن است توصیه شود از نوع سرویس simple استفاده شود تا اطمینان حاصل شود که منطق تراکنش مدیر سرویس تحت تأثیر چنین عملیات بالقوه کند و وابستگیهای پنهانی قرار نمیگیرد، زیرا این تنها نوع سرویسی است که در آن مدیر سرویس پیش از ادامه کار منتظر تکمیل چنین عملیات راهاندازی اجرای سرویس نخواهد ماند.
ExitType=
معمولاً توصیه میشود زمانی که یک سرویس دارای مدل انشعاب (forking) مشخص است و یک فرآیند اصلی را میتوان بهطور قابل اعتماد تعیین کرد، از ExitType=main استفاده شود. ExitType=cgroup برای برنامههایی در نظر گرفته شده است که مدل انشعاب آنها از قبل مشخص نیست و ممکن است فرآیند اصلی مشخصی نداشته باشند. این گزینه برای سرویسهای گذرا یا خودکار تولیدشده، مانند برنامههای گرافیکی درون یک محیط دسکتاپ، بسیار مناسب است.
در نسخه 250 اضافه شد.
RemainAfterExit=
GuessMainPID=
PIDFile=
توجه داشته باشید که در پروژههای مدرن باید از فایلهای PID اجتناب شود. در صورت امکان از Type=notify، Type=notify-reload یا Type=simple استفاده کنید، که برای تعیین فرآیند اصلی سرویس نیازی به استفاده از فایلهای PID ندارند و از انشعابهای غیرضروری جلوگیری میکنند.
BusName=
ExecStart=
مگر اینکه Type= برابر با oneshot باشد، دقیقاً یک دستور باید داده شود. هنگامی که Type=oneshot استفاده میشود، این تنظیم ممکن است چندین بار برای تعریف چندین دستور جهت اجرا استفاده شود. اگر رشته خالی به این گزینه اختصاص داده شود، فهرست دستورات برای شروع بازنشانی میشود و انتسابهای قبلی این گزینه بیاثر خواهند بود. اگر هیچ ExecStart= مشخص نشده باشد، سرویس باید دارای RemainAfterExit=yes و حداقل یک خط ExecStop= تنظیمشده باشد. (سرویسهایی که فاقد هر دو ExecStart= و ExecStop= باشند معتبر نیستند.)
اگر بیش از یک دستور پیکربندی شده باشد، دستورات به ترتیب ترتیبی که در فایل واحد ظاهر میشوند فراخوانی میگردند. اگر یکی از دستورات با شکست مواجه شود (و پیشوند "-" نداشته باشد)، خطوط دیگر اجرا نمیشوند و واحد ناموفق تلقی میشود.
مگر اینکه Type=forking تنظیم شده باشد، فرآیندی که از طریق این خط فرمان شروع میشود فرآیند اصلی دیمن در نظر گرفته خواهد شد.
ExecStartPre=, ExecStartPost=
اگر هر یک از آن دستورات (که پیشوند "-" ندارند) با شکست مواجه شوند، بقیه اجرا نمیشوند و واحد ناموفق تلقی میشود.
دستورات ExecStart= تنها پس از اینکه تمام دستورات ExecStartPre= که پیشوند "-" نداشتند با موفقیت خارج شدند، اجرا میشوند.
دستورات ExecStartPost= تنها پس از فراخوانی موفقیتآمیز دستورات مشخصشده در ExecStart=، همانطور که توسط Type= تعیین میشود اجرا میگردند (یعنی فرآیند برای Type=simple یا Type=idle شروع شده باشد، آخرین فرآیند ExecStart= برای Type=oneshot با موفقیت خارج شده باشد، فرآیند اولیه برای Type=forking با موفقیت خارج شده باشد، "READY=1" برای Type=notify/Type=notify-reload ارسال شده باشد، یا BusName= برای Type=dbus تصاحب شده باشد).
توجه داشته باشید که ExecStartPre= نباید برای شروع فرآیندهای با اجرای طولانی استفاده شود. تمام فرآیندهایی که توسط فرآیندهای فراخوانیشده از طریق ExecStartPre= انشعاب یافتهاند، قبل از اجرای فرآیند بعدی سرویس کشته خواهند شد.
توجه داشته باشید که اگر هر یک از دستورات مشخصشده در ExecStartPre=، ExecStart= یا ExecStartPost= با شکست مواجه شوند (و پیشوند "-" نداشته باشند، بالا را ببینید) یا قبل از بالا آمدن کامل سرویس مهلت زمانی آنها به پایان برسد، اجرا با دستورات مشخصشده در ExecStopPost= ادامه مییابد و از دستورات موجود در ExecStop= صرفنظر میشود.
توجه داشته باشید که اجرای ExecStartPost= به منظور قیدهای ترتیببندی Before=/After= در نظر گرفته میشود.
ExecCondition=
رفتار این گزینه شبیه ترکیبی از ExecStartPre= و بررسی شرط است: هنگامی که یک دستور ExecCondition= با کد خروج ۱ تا ۲۵۴ (شامل هر دو) خارج میشود، دستورات باقیمانده نادیده گرفته میشوند و واحد به عنوان ناموفق علامتگذاری نمیشود. با این حال، اگر یک دستور ExecCondition= با کد ۲۵۵ یا به صورت غیرعادی (مانند اتمام مهلت زمانی، کشته شدن توسط سیگنال و غیره) خارج شود، واحد ناموفق تلقی میشود (و دستورات باقیمانده نادیده گرفته میشوند). کد خروج ۰ یا آنهایی که با SuccessExitStatus= مطابقت دارند، اجرا را به سمت دستورات بعدی ادامه خواهند داد.
همان توصیهها درباره عدم اجرای فرآیندهای با اجرای طولانی در ExecStartPre= برای ExecCondition= نیز صدق میکند. ExecCondition= همچنین در صورت هرگونه خروج غیر صفر یا غیرعادی، مانند موارد توصیفشده در بالا، دستورات موجود در ExecStopPost= را به عنوان بخشی از توقف سرویس اجرا خواهد کرد.
در نسخه 243 اضافه شد.
ExecReload=
یک متغیر محیطی ویژه اضافی تنظیم شده است: در صورت مشخص بودن، $MAINPID روی فرآیند اصلی دیمن تنظیم میشود و ممکن است برای خطوط فرمانی مانند خط زیر استفاده شود:
ExecReload=kill -HUP $MAINPID
با این حال، توجه داشته باشید که بارگذاری مجدد دیمن از طریق صفبندی یک سیگنال (مانند خط نمونه بالا) معمولاً انتخاب خوبی نیست، زیرا این یک عملیات ناهمگام است و بنابراین هنگام ترتیببندی بارگذاری مجدد چندین سرویس نسبت به یکدیگر مناسب نیست. بنابراین اکیداً توصیه میشود که یا از Type=notify-reload به جای ExecReload= استفاده شود، یا ExecReload= روی دستوری تنظیم گردد که نه تنها بارگذاری مجدد پیکربندی دیمن را آغاز کند، بلکه بهطور همگام منتظر تکمیل آن بماند. برای مثال، dbus-broker?R(1) از موارد زیر استفاده میکند:
ExecReload=busctl call org.freedesktop.DBus \
/org/freedesktop/DBus org.freedesktop.DBus \
ReloadConfig
ExecStop=
توجه داشته باشید که معمولاً مشخص کردن دستوری برای این تنظیم که صرفاً از سرویس درخواست خاتمه کند (برای مثال با ارسال نوعی سیگنال خاتمه به آن)، اما منتظر انجام آن نماند، کافی نیست. از آنجا که فرآیندهای باقیمانده سرویس طبق KillMode= و KillSignal= یا RestartKillSignal= همانطور که در بالا توصیف شد بلافاصله پس از خروج دستور کشته میشوند، این ممکن است منجر به یک توقف پاک نشود. بنابراین دستور مشخصشده باید یک عملیات همگام باشد، نه ناهمگام.
توجه داشته باشید که دستورات مشخصشده در ExecStop= تنها زمانی اجرا میشوند که سرویس ابتدا با موفقیت شروع شده باشد. اگر سرویس اصلاً شروع نشده باشد، یا در صورتی که راهاندازی آن با شکست مواجه شده باشد (برای مثال به این دلیل که هر یک از دستورات مشخصشده در ExecStart=، ExecStartPre= یا ExecStartPost= با شکست مواجه شده باشند [و پیشوند "-" نداشته باشند، بالا را ببینید] یا مهلت زمانی آنها سپری شده باشد)، فراخوانی نمیشوند. برای فراخوانی دستورات در زمانی که راهاندازی سرویس به درستی انجام نشده و مجدداً خاموش میشود، از ExecStopPost= استفاده کنید. همچنین توجه داشته باشید که عملیات توقف همیشه در صورتی که سرویس با موفقیت شروع شده باشد انجام میشود، حتی اگر فرآیندهای موجود در سرویس خودبهخود خاتمه یافته باشند یا کشته شده باشند. دستورات توقف باید برای مواجهه با چنین حالتی آماده باشند. در صورتی که systemd بداند فرآیند اصلی در زمان فراخوانی دستورات توقف خارج شده است، $MAINPID تنظیمنشده خواهد بود.
درخواستهای راهاندازی مجدد سرویس به صورت عملیات توقف و به دنبال آن عملیات شروع پیادهسازی میشوند. این بدان معناست که ExecStop= و ExecStopPost= در طول عملیات راهاندازی مجدد سرویس اجرا میشوند.
توصیه میشود از این تنظیم برای دستوراتی استفاده شود که با سرویس ارتباط برقرار کرده و درخواست خاتمه پاک دارند. برای مراحل پاکسازی پس از توقف، در عوض از ExecStopPost= استفاده کنید.
ExecStopPost=
توصیه میشود از این تنظیم برای عملیات پاکسازی استفاده شود که باید حتی در صورت عدم موفقیت در راهاندازی صحیح سرویس نیز اجرا شوند. دستورات پیکربندیشده با این تنظیم باید بتوانند حتی اگر سرویس در نیمه راه راهاندازی با شکست مواجه شده و دادههای ناقص مقداردهیشده باقی گذاشته باشد، کار کنند. از آنجا که فرآیندهای سرویس احتمالاً هنگام اجرای دستورات مشخصشده با این تنظیم از قبل خارج شدهاند، نباید سعی کنند با آنها ارتباط برقرار نمایند.
توجه داشته باشید که تمام دستوراتی که با این تنظیم پیکربندی شدهاند با کد نتیجه سرویس، و همچنین کد خروج و وضعیت فرآیند اصلی، که در متغیرهای محیطی $SERVICE_RESULT، $EXIT_CODE و $EXIT_STATUS تنظیم شدهاند فراخوانی میشوند؛ برای جزئیات به systemd.exec(5) مراجعه کنید.
توجه داشته باشید که اجرای ExecStopPost= به منظور قیدهای ترتیببندی Before=/After= در نظر گرفته میشود.
RestartSec=
RestartSteps=
مثال:
RestartSec=10s RestartSteps=4 RestartMaxDelaySec=160s
این مقادیر فاصلههای راهاندازی مجدد زیر را ایجاد میکند: 10s، 20s، 40s، 80s، 160s، 160s، 160s و غیره. به درونیابی هندسی و نسبت ثابت حاصل میان بازهها توجه کنید؛ در اینجا ۲ است. فرمول برای ratio عبارت است از (RestartMaxDelaySec / RestartSec)^(1 / RestartSteps). یک تأخیر (تکرارشونده) برابر با RestartMaxDelaySec= همیشه پس از RestartSteps + 1 گام به دست میآید.
این تنظیم تنها در صورتی مؤثر است که RestartMaxDelaySec= نیز تنظیم شده باشد و RestartSec= صفر نباشد.
در نسخه 254 اضافه شد.
RestartMaxDelaySec=
این تنظیم تنها در صورتی مؤثر است که RestartSteps= نیز تنظیم شده باشد و RestartSec= صفر نباشد.
در نسخه 254 اضافه شد.
TimeoutStartSec=
اگر سرویسی از Type=notify/Type=notify-reload پیام "EXTEND_TIMEOUT_USEC=..." را ارسال کند، ممکن است باعث شود زمان راهاندازی فراتر از TimeoutStartSec= تمدید شود. اولین دریافت این پیام باید قبل از فراتر رفتن از TimeoutStartSec= رخ دهد، و پس از تمدید زمان راهاندازی فراتر از TimeoutStartSec=، مدیر سرویس به سرویس اجازه میدهد تا به راهاندازی خود ادامه دهد، مشروط بر اینکه سرویس پیام "EXTEND_TIMEOUT_USEC=..." را در بازه زمانی مشخصشده تکرار کند تا زمانی که وضعیت راهاندازی سرویس با "READY=1" پایان یابد (نگاه کنید به sd_notify(3)).
توجه داشته باشید که مهلت زمانی راهاندازی برای بارگذاری مجدد سرویس نیز اعمال میشود، صرفنظر از اینکه از طریق ExecReload= پیادهسازی شده باشد یا از طریق منطق بارگذاری مجدد فعالشده از طریق Type=notify-reload. اگر بارگذاری مجدد در مدت زمان پیکربندیشده تکمیل نشود، بارگذاری مجدد ناموفق در نظر گرفته میشود و سرویس به اجرای خود با پیکربندی قدیمی ادامه میدهد. این امر بر سرویس در حال اجرا تأثیری نخواهد گذاشت، اما ثبت وقایع شده و برای مثال باعث شکست systemctl reload خواهد شد.
در نسخه 188 اضافه شد.
TimeoutStopSec=
اگر سرویسی از Type=notify/Type=notify-reload پیام "EXTEND_TIMEOUT_USEC=..." را ارسال کند، ممکن است باعث شود زمان توقف فراتر از TimeoutStopSec= تمدید شود. اولین دریافت این پیام باید قبل از فراتر رفتن از TimeoutStopSec= رخ دهد، و پس از تمدید زمان توقف فراتر از TimeoutStopSec=، مدیر سرویس به سرویس اجازه میدهد تا به توقف خود ادامه دهد، مشروط بر اینکه سرویس پیام "EXTEND_TIMEOUT_USEC=..." را در بازه زمانی مشخصشده تکرار کند، یا خود خاتمه یابد (نگاه کنید به sd_notify(3)).
در نسخه 188 اضافه شد.
TimeoutAbortSec=
یک مقدار بدون واحد بر حسب ثانیه، یا یک مقدار بازه زمانی مانند "5min 20s" میگیرد. یک مقدار خالی برای صرفنظر از مدیریت مهلت توقف اختصاصی دیدهبان و بازگشت به TimeoutStopSec= ارسال کنید. برای غیرفعال کردن منطق مهلت زمانی، "infinity" را ارسال کنید. مقدار پیشفرض آن DefaultTimeoutAbortSec= از فایل پیکربندی مدیر است (به systemd-system.conf(5) مراجعه کنید).
اگر سرویسی از Type=notify/Type=notify-reload سیگنال SIGABRT را خودش مدیریت کند (به جای تکیه بر هسته برای نوشتن تخلیه حافظه) میتواند "EXTEND_TIMEOUT_USEC=..." را برای تمدید زمان لغو فراتر از TimeoutAbortSec= ارسال کند. اولین دریافت این پیام باید قبل از فراتر رفتن از TimeoutAbortSec= رخ دهد، و پس از تمدید زمان لغو فراتر از TimeoutAbortSec=، مدیر سرویس به سرویس اجازه میدهد تا به لغو ادامه دهد، مشروط بر اینکه سرویس پیام "EXTEND_TIMEOUT_USEC=..." را در بازه زمانی مشخصشده تکرار کند، یا خود خاتمه یابد (نگاه کنید به sd_notify(3)).
در نسخه 243 اضافه شد.
TimeoutSec=
TimeoutStartFailureMode=, TimeoutStopFailureMode=
اگر روی terminate تنظیم شود، سرویس با ارسال سیگنال مشخصشده در KillSignal= به صورت مسالمتآمیز خاتمه مییابد (پیشفرض SIGTERM است، به systemd.kill(5) مراجعه کنید). اگر سرویس خاتمه نیابد، FinalKillSignal= پس از TimeoutStopSec= ارسال میشود. اگر abort تنظیم شده باشد، WatchdogSignal= به جای آن ارسال میشود و TimeoutAbortSec= قبل از ارسال FinalKillSignal= اعمال میگردد. این تنظیم ممکن است برای تجزیه و تحلیل سرویسهایی که به صورت متناوب در راهاندازی یا خاموش شدن با شکست مواجه میشوند استفاده شود. با استفاده از kill، سرویس بلافاصله با ارسال FinalKillSignal= بدون هیچگونه مهلت زمانی دیگری خاتمه مییابد. این تنظیم میتواند برای تسریع در خاموش شدن سرویسهای ناموفق استفاده شود.
در نسخه 246 اضافه شد.
RuntimeMaxSec=
اگر سرویسی از Type=notify/Type=notify-reload پیام "EXTEND_TIMEOUT_USEC=..." را ارسال کند، ممکن است باعث شود زمان اجرا فراتر از RuntimeMaxSec= تمدید شود. اولین دریافت این پیام باید قبل از فراتر رفتن از RuntimeMaxSec= رخ دهد، و پس از تمدید زمان اجرا فراتر از RuntimeMaxSec=، مدیر سرویس به سرویس اجازه میدهد تا به اجرای خود ادامه دهد، مشروط بر اینکه سرویس پیام "EXTEND_TIMEOUT_USEC=..." را در بازه زمانی مشخصشده تکرار کند تا زمانی که خاموش شدن سرویس با "STOPPING=1" (یا خاتمه) حاصل شود (نگاه کنید به sd_notify(3)).
در نسخه 229 اضافه شد.
RuntimeRandomizedExtraSec=
در نسخه 250 اضافه شد.
WatchdogSec=
Restart=
یکی از مقادیر no، on-success، on-failure، on-abnormal، on-watchdog، on-abort یا always را میگیرد. اگر روی no (پیشفرض) تنظیم شود، سرویس مجدداً راهاندازی نخواهد شد. اگر روی on-success تنظیم شود، تنها زمانی که فرآیند سرویس به صورت پاک خارج شود مجدداً راهاندازی میگردد. در این زمینه، یک خروج پاک به معنای هر یک از موارد زیر است:
اگر روی on-failure تنظیم شود، سرویس زمانی که فرآیند با کد خروج غیر صفر خارج شود، توسط یک سیگنال خاتمه یابد (از جمله در تخلیه حافظه، اما به استثنای چهار سیگنال فوقالذکر)، هنگامی که یک عملیات (مانند بارگذاری مجدد سرویس) به پایان مهلت زمانی برسد، و زمانی که مهلت زمانی دیدهبان پیکربندیشده فعال شود، مجدداً راهاندازی خواهد شد. اگر روی on-abnormal تنظیم شود، سرویس هنگامی که فرآیند توسط یک سیگنال خاتمه یابد (از جمله در تخلیه حافظه، به استثنای چهار سیگنال فوقالذکر)، هنگامی که مهلت زمانی یک عملیات سپری شود، یا زمانی که مهلت زمانی دیدهبان فعال گردد مجدداً راهاندازی خواهد شد. اگر روی on-abort تنظیم شود، سرویس تنها در صورتی مجدداً راهاندازی میشود که فرآیند سرویس به دلیل یک سیگنال مدیریتنشده که به عنوان وضعیت خروج پاک مشخص نشده است خارج شود. اگر روی on-watchdog تنظیم شود، سرویس تنها در صورتی مجدداً راهاندازی میشود که مهلت دیدهبان برای سرویس منقضی شود. اگر روی always تنظیم شود، سرویس بدون توجه به اینکه آیا به صورت پاک خارج شده یا خیر، به صورت غیرعادی با سیگنال خاتمه یافته، یا به مهلت زمانی رسیده است، مجدداً راهاندازی خواهد شد. توجه داشته باشید که سرویسهای Type=oneshot هرگز با وضعیت خروج پاک مجدداً راهاندازی نمیشوند، یعنی مقادیر always و on-success برای آنها رد میشود.
جدول ۱. علل خروج و اثر تنظیمات Restart=
| تنظیمات Restart/علل خروج | no | always | on-success | on-failure | on-abnormal | on-abort | on-watchdog |
| کد خروج یا سیگنال پاک | X | X | |||||
| کد خروج غیرپاک | X | X | |||||
| سیگنال غیرپاک | X | X | X | X | |||
| اتمام مهلت زمانی (Timeout) | X | X | X | ||||
| دیدهبان (Watchdog) | X | X | X | X |
به عنوان
استثناهایی
بر تنظیمات
فوق، اگر کد
خروج یا
سیگنال در
RestartPreventExitStatus= (به زیر
مراجعه
کنید) مشخص
شده باشد یا
سرویس با systemctl
stop یا
عملیاتی
معادل
متوقف شود،
سرویس
مجدداً
راهاندازی
نخواهد شد.
همچنین،
اگر کد خروج
یا سیگنال
در RestartForceExitStatus= (به
زیر مراجعه
کنید) مشخص
شده باشد،
سرویسها
همیشه
مجدداً
راهاندازی
خواهند شد.
توجه داشته باشید که راهاندازی مجدد سرویس مشمول محدودیت نرخ شروع واحد است که با StartLimitIntervalSec= و StartLimitBurst= پیکربندی میشود، برای جزئیات به systemd.unit(5) مراجعه کنید.
تنظیم این گزینه روی on-failure انتخاب توصیهشده برای سرویسهای با اجرای طولانی است، تا با تلاش برای بازیابی خودکار از خطاها، قابلیت اطمینان افزایش یابد. برای سرویسهایی که باید بتوانند به انتخاب خود خاتمه یابند (و از راهاندازی مجدد فوری جلوگیری کنند)، on-abnormal یک انتخاب جایگزین است.
RestartMode=
در نسخه 254 اضافه شد.
این گزینه در مواردی مفید است که یک وابستگی ممکن است موقتاً با شکست مواجه شود اما ما نمیخواهیم این شکستهای موقت باعث ناموفق شدن واحدهای وابسته شوند. واحدهای وابسته از این شکستهای موقت مطلع نمیشوند.
در نسخه 254 اضافه شد.
در نسخه 257 اضافه شد.
در نسخه 254 اضافه شد.
SuccessExitStatus=
توجه داشته باشید که این تنظیم نگاشت بین وضعیتهای خروج عددی و نام آنها را تغییر نمیدهد؛ یعنی صرفنظر از نحوه استفاده از این تنظیم، 0 همچنان به "SUCCESS" نگاشته میشود (و بنابراین معمولاً در خروجی ابزارها به صورت "0/SUCCESS" نشان داده میشود) و 1 به "FAILURE" (و بنابراین معمولاً به صورت "1/FAILURE" نشان داده میشود)، و به همین ترتیب. این گزینه فقط اثر این وضعیتهای خروج و نحوه انتشار آنها به وضعیت کلی سرویس را کنترل میکند.
این گزینه ممکن است بیش از یک بار ظاهر شود، که در این صورت فهرست وضعیتهای خروج موفق ادغام میشود. اگر رشته خالی به این گزینه اختصاص داده شود، فهرست بازنشانی میشود و تمام انتسابهای قبلی این گزینه بیاثر خواهند بود.
مثال ۱. یک سرویس با تنظیم SuccessExitStatus=
SuccessExitStatus=TEMPFAIL 250 SIGKILL
وضعیت خروج 75 (TEMPFAIL)، 250، و سیگنال خاتمه SIGKILL به عنوان خاتمه پاک سرویس تلقی میشوند.
نکته: systemd-analyze exit-status ممکن است برای فهرست کردن وضعیتهای خروج و ترجمه بین مقادیر عددی وضعیت و نامها استفاده شود.
در نسخه 189 اضافه شد.
RestartPreventExitStatus=
مثال ۲. یک سرویس با تنظیم RestartPreventExitStatus=
RestartPreventExitStatus=TEMPFAIL 250 SIGKILL
وضعیت خروج 75 (TEMPFAIL)، 250، و سیگنال خاتمه SIGKILL منجر به راهاندازی مجدد خودکار سرویس نخواهند شد.
این گزینه ممکن است بیش از یک بار ظاهر شود، که در این صورت فهرست وضعیتهای مانع راهاندازی مجدد ادغام میشود. اگر رشته خالی به این گزینه اختصاص داده شود، فهرست بازنشانی میشود و تمام انتسابهای قبلی این گزینه بیاثر خواهند بود.
توجه داشته باشید که این تنظیم بر فرآیندهای پیکربندیشده از طریق ExecStartPre=، ExecStartPost=، ExecStop=، ExecStopPost= یا ExecReload= هیچ اثری ندارد، بلکه تنها بر فرآیند اصلی سرویس اثر میگذارد، یعنی فرآیندی که توسط ExecStart= فراخوانی شده است یا (بسته به Type=، PIDFile= و غیره) فرآیند اصلی پیکربندیشده به نحوی دیگر.
در نسخه 189 اضافه شد.
RestartForceExitStatus=
توجه داشته باشید که برای سرویسهای Type=oneshot، یک وضعیت خروج موفقیتآمیز مانع از راهاندازی مجدد خودکار آنها میشود، صرفنظر از اینکه وضعیتهای خروج مربوطه در این گزینه فهرست شده باشند یا خیر.
در نسخه 215 اضافه شد.
RootDirectoryStartOnly=
NonBlocking=
توجه داشته باشید که اگر یک واحد سوکت یکسان برای انتقال به چندین واحد سرویس پیکربندی شده باشد (از طریق تنظیم Sockets=، به زیر مراجعه کنید)، و این سرویسها دارای پیکربندیهای متفاوتی از NonBlocking= باشند، وضعیت دقیق O_NONBLOCK به ترتیبی که این سرویسها فراخوانی میشوند بستگی دارد، و احتمالاً پس از اینکه کد سرویس توصیفکننده فایل سوکت را در اختیار گرفت تغییر خواهد کرد، صرفاً به این دلیل که وضعیت O_NONBLOCK یک سوکت بین تمام توصیفکنندههای فایلی که به آن ارجاع دارند مشترک است. از این رو ضروری است که تمام سرویسهایی که یک سوکت مشترک دارند از یک پیکربندی یکسان برای NonBlocking= استفاده کنند، و پرچم را در کد سرویس نیز تغییر ندهند.
NotifyAccess=
توجه داشته باشید که اعلانهای sd_notify() ممکن است تنها در صورتی بهطور صحیح به واحدها نسبت داده شوند که یا فرآیند ارسالکننده هنوز در زمان پردازش پیام توسط PID 1 وجود داشته باشد، یا فرآیند ارسالکننده بهطور صریح توسط مدیر سرویس در زمان اجرا ردیابی شود. مورد دوم زمانی صادق است که مدیر سرویس در ابتدا فرآیند را انشعاب داده باشد، یعنی در تمام فرآیندهایی که با main یا exec مطابقت دارند. برعکس، اگر یک فرآیند کمکی از واحد یک پیام sd_notify() ارسال کند و بلافاصله خارج شود، ممکن است مدیر سرویس نتواند به درستی پیام را به واحد نسبت دهد، و بنابراین آن را نادیده خواهد گرفت، حتی اگر NotifyAccess=all برای آن تنظیم شده باشد.
بنابراین، برای از بین بردن تمام شرایط رقابتی (race conditions) مربوط به جستجوی واحد کلاینت و انتساب صحیح اعلانها به واحدها، میتوان از sd_notify_barrier() استفاده کرد. این فراخوانی به عنوان یک نقطه همگامسازی عمل میکند و تضمین میکند که تمام اعلانهای ارسالشده قبل از این فراخوانی، هنگام بازگشت موفقیتآمیز آن توسط مدیر سرویس دریافت شدهاند. استفاده از sd_notify_barrier() برای کلاینتهایی که توسط مدیر سرویس فراخوانی نمیشوند مورد نیاز است، در غیر این صورت این سازوکار همگامسازی برای انتساب اعلانها به واحد غیرضروری است.
Sockets=
توجه داشته باشید که ممکن است توصیفکنندههای فایل سوکت یکسان به چندین فرآیند بهطور همزمان منتقل شوند. همچنین توجه داشته باشید که ممکن است بر روی ترافیک سوکت ورودی سرویسی متفاوت از سرویسی که در نهایت برای به ارث بردن توصیفکنندههای فایل سوکت پیکربندی شده است، فعال شود. یا به عبارت دیگر: تنظیم Service= در واحدهای .socket لازم نیست با معکوس تنظیم Sockets= در واحد .service مربوطه مطابقت داشته باشد.
این گزینه ممکن است بیش از یک بار ظاهر شود، که در این صورت فهرست واحدهای سوکت ادغام میشود. توجه داشته باشید که پس از تنظیم، پاک کردن مجدد فهرست سوکتها (برای مثال، با اختصاص رشته خالی به این گزینه) پشتیبانی نمیشود.
FileDescriptorStoreMax=
دستور fdstore از systemd-analyze(1) ممکن است برای فهرست کردن محتوای فعلی مخزن توصیفکننده فایل یک سرویس استفاده شود.
توجه داشته باشید که مدیر سرویس توصیفکنندههای فایل موجود در مخزن توصیفکننده فایل را تنها به فرآیندهای خود سرویس منتقل میکند، و هرگز از طریق IPC یا موارد مشابه به سایر کلاینتها منتقل نخواهد کرد. با این حال، به کلاینتهای غیرممتاز اجازه میدهد تا فهرست توصیفکنندههای فایلِ در حال حاضر بازِ یک سرویس را جویا شوند. بنابراین دادههای حساس را میتوان با خیال راحت در داخل فایلهای ارجاعشده قرار داد، اما نباید به متادادههای (مثلاً در نام فایلها) توصیفکنندههای فایل ذخیرهشده پیوست شوند.
اگر این گزینه روی مقداری غیر صفر تنظیم شود، متغیر محیطی $FDSTORE برای فرآیندهای فراخوانیشده برای این سرویس تنظیم خواهد شد. برای جزئیات به systemd.exec(5) مراجعه کنید.
برای اطلاعات بیشتر در مورد مخزن توصیفکننده فایل، بررسی اجمالی File Descriptor Store[1] را ببینید.
در نسخه 219 اضافه شد.
FileDescriptorStorePreserve=
از systemctl clean --what=fdstore ... برای آزادسازی صریح مخزن توصیفکننده فایل استفاده کنید.
در نسخه 254 اضافه شد.
USBFunctionDescriptors=
در نسخه 227 اضافه شد.
USBFunctionStrings=
در نسخه 227 اضافه شد.
OOMPolicy=
این تنظیم یکی از مقادیر continue، stop یا kill را میگیرد. اگر روی continue تنظیم شود و فرآیندی در واحد توسط قاتل OOM کشته شود، این رویداد ثبت وقایع میشود اما واحد به اجرای خود ادامه میدهد. اگر روی stop تنظیم شود، رویداد ثبت وقایع شده اما واحد توسط مدیر سرویس به صورت پاک خاتمه مییابد. اگر روی kill تنظیم شود و یکی از فرآیندهای واحد توسط قاتل OOM کشته شود، به هسته دستور داده میشود که تمام فرآیندهای باقیمانده واحد را نیز با تنظیم ویژگی memory.oom.group روی 1 بکشد؛ همچنین صفحه مستندات هسته Control Group v2[3] را ببینید.
پیشفرض روی تنظیمی است که DefaultOOMPolicy= در systemd-system.conf(5) روی آن قرار دارد، به جز برای واحدهایی که Delegate= در آنها فعال است، که در آنجا پیشفرض continue است.
از تنظیم OOMScoreAdjust= برای پیکربندی اینکه آیا فرآیندهای واحد باید نامزدهای ارجح یا کمارجحتر برای خاتمه فرآیند توسط منطق قاتل OOM لینوکس تلقی شوند، استفاده کنید. برای جزئیات به systemd.exec(5) مراجعه نمایید.
این تنظیم همچنین بر systemd-oomd.service(8) اعمال میشود. مشابه کشتنهای OOM انجامشده توسط هسته، این تنظیم وضعیت واحد را پس از اینکه systemd-oomd یک cgroup مرتبط با آن را میکشد تعیین میکند.
در نسخه 243 اضافه شد.
OpenFile=
فایل یا سوکت توسط مدیر سرویس باز میشود و توصیفکننده فایل به سرویس منتقل میگردد. اگر مسیر یک سوکت باشد، connect() را روی آن فراخوانی میکنیم. برای جزئیات بیشتر در مورد نحوه بازیابی این توصیفکنندههای فایل به sd_listen_fds(3) مراجعه کنید.
این تنظیم برای این مفید است که به سرویسها اجازه دهد به فایلها/سوکتهایی دسترسی داشته باشند که خودشان نمیتوانند به آنها دسترسی پیدا کنند (به دلیل اجرا در یک فضاینام سوارکردن مجزا، نداشتن امتیازات و غیره).
این تنظیم را میتوان چندین بار مشخص کرد، که در این صورت تمام مسیرهای مشخصشده باز میشوند و توصیفکنندههای فایل به سرویس منتقل میگردند. اگر رشته خالی به آن اختصاص داده شود، کل فهرست فایلهای باز که قبل از این تعریف شدهاند بازنشانی میشود.
در نسخه 253 اضافه شد.
ReloadSignal=
در نسخه 253 اضافه شد.
برای تنظیمات بیشتر systemd.unit(5)، systemd.exec(5) و systemd.kill(5) را بررسی کنید.
خطوط فرمان (COMMAND LINES)
این بخش به توصیف تجزیه خط فرمان و جایگزینی متغیرها و مشخصکنندهها برای گزینههای ExecStart=، ExecStartPre=، ExecStartPost=، ExecReload=، ExecStop=، ExecStopPost= و ExecCondition= میپردازد.
چندین خط فرمان را میتوان با استفاده مکرر از تنظیم مربوطه مشخص کرد.
هر خط فرمان با استفاده از قوانین توصیفشده در بخش "Quoting" در systemd.syntax(7) از نقلقول خارج میشود. اولین مورد تبدیل به دستور برای اجرا میشود، و موارد بعدی آرگومانهای آن خواهند بود.
این نحو از نحو شل الهام گرفته شده است، اما فقط نویسههای متا و بسطهای توصیفشده در بندهای زیر فهمیده میشوند، و بسط متغیرها متفاوت است. به ویژه، تغییر مسیر با استفاده از "<"، "<<"، ">" و ">>"، لولهها (pipes) با استفاده از "|"، اجرای برنامهها در پسزمینه با استفاده از "&" و سایر عناصر نحو شل پشتیبانی نمیشوند.
دستور برای اجرا ممکن است شامل فاصله باشد، اما نویسههای کنترلی مجاز نیستند.
هر دستور ممکن است با تعدادی نویسه ویژه پیشوندگذاری شود:
جدول ۲. پیشوندهای ویژه فایل اجرایی
| پیشوند | اثر |
| "@" | اگر مسیر اجرایی با "@" پیشوندگذاری شود، دومین توکن مشخصشده به عنوان argv[0] به فرآیند اجراشده منتقل میشود (به جای نام فایل واقعی)، و پس از آن سایر آرگومانهای مشخصشده قرار میگیرند. |
| "-" | اگر مسیر اجرایی با "-" پیشوندگذاری شود، کد خروج دستوری که معمولاً ناموفق تلقی میشود (یعنی وضعیت خروج غیر صفر یا خروج غیرعادی به دلیل سیگنال) ثبت میشود، اما اثر دیگری نخواهد داشت و معادل موفقیت تلقی میگردد. |
| ":" | اگر مسیر اجرایی با ":" پیشوندگذاری شود، جایگزینی متغیر محیطی (همانطور که در زیر این جدول شرح داده شده است) اعمال نخواهد شد. |
| "+" | اگر مسیر اجرایی با "+" پیشوندگذاری شود، فرآیند با تمام امتیازات اجرا میشود. در این حالت، محدودیتهای امتیازی پیکربندیشده با User=، Group=، CapabilityBoundingSet= یا گزینههای مختلف فضاینام سیستم فایل (مانند PrivateDevices=، PrivateTmp=) برای خط فرمان فراخوانیشده اعمال نمیشوند (اما همچنان بر هر خط دیگر ExecStart=، ExecStop= و غیره اثر میگذارند). با این حال، توجه داشته باشید که این کار گزینههایی را که برای کل گروه کنترلی اعمال میشوند دور نمیزند، مانند DevicePolicy=؛ برای فهرست کامل به systemd.resource-control(5) مراجعه کنید. |
| "!" | مشابه با نویسه "+" که در بالا بحث شد، این پیشوند اجازه فراخوانی خطوط فرمان با امتیازات ارتقایافته را میدهد. با این حال، برخلاف "+"، نویسه "!" منحصراً اثر User=، Group= و SupplementaryGroups= را تغییر میدهد، یعنی فقط بخشهایی که بر گواهیهای کاربر و گروه اثر میگذارند. توجه داشته باشید که این تنظیم ممکن است با DynamicUser= ترکیب شود، که در این صورت یک جفت کاربر/گروه پویا قبل از فراخوانی دستور تخصیص مییابد، اما تغییر گواهیها به خود فرآیند اجراشده واگذار میشود. |
| "!!" | این پیشوند بسیار شبیه به "!" است، اما تنها در سیستمهایی اثر دارد که فاقد پشتیبانی از قابلیتهای پیرامونی فرآیند (ambient process capabilities) هستند، یعنی بدون پشتیبانی از AmbientCapabilities=. این پیشوند برای فایلهای واحدی در نظر گرفته شده است که از قابلیتهای پیرامونی بهره میبرند تا فرآیندها را با حداقل امتیازات در هر کجا که امکانپذیر است اجرا کنند و در عین حال با سیستمهایی که فاقد پشتیبانی از قابلیتهای پیرامونی هستند سازگار بمانند. توجه داشته باشید که وقتی از "!!" استفاده میشود و سیستمی فاقد پشتیبانی از قابلیت پیرامونی شناسایی میگردد، هر بخش پیکربندیشده SystemCallFilter= و CapabilityBoundingSet= بهطور ضمنی تغییر میکند تا به فرآیندهای ایجادشده اجازه دهد خودشان گواهیها و قابلیتها را رها کنند، حتی اگر این کار به گونهای پیکربندی شده باشد که مجاز نباشد. علاوه بر این، اگر از این پیشوند استفاده شود و سیستمی فاقد پشتیبانی از قابلیت پیرامونی شناسایی گردد، از AmbientCapabilities= صرفنظر شده و اعمال نخواهد شد. در سیستمهایی که از قابلیتهای پیرامونی پشتیبانی میکنند، "!!" هیچ اثری ندارد و زائد است. |
"@"،
"-"، ":"، و یکی
از "+"/"!"/"!!"
میتوانند
با هم
استفاده
شوند و
میتوانند
به هر
ترتیبی
ظاهر شوند.
با این حال،
در هر زمان
تنها
میتوان از
یکی از "+"،
"!"، "!!"
استفاده
کرد.
برای هر دستور، اولین آرگومان باید یک مسیر مطلق به یک فایل اجرایی یا یک نام فایل ساده بدون هیچگونه اسلش باشد. اگر دستور یک مسیر کامل (مطلق) نباشد، با استفاده از یک مسیر جستجوی ثابت که در زمان کامپایل تعیین شده است به یک مسیر کامل حل میشود. دایرکتوریهای جستجو شده شامل /usr/local/bin/، /usr/bin/ و همتایان sbin/ آنها هستند (فقط در سیستمهایی که از bin/ و sbin/ تفکیکشده استفاده میکنند). بنابراین در مورد فایلهای اجرایی واقع در هر یک از دایرکتوریهای "استاندارد"، استفاده از تنها نام فایل اجرایی ایمن است، و در موارد دیگر باید از یک مسیر مطلق استفاده شود. راهنمایی: این مسیر جستجو را میتوان با استفاده از systemd-path search-binaries-default استعلام کرد.
خط فرمان مشخصکنندههای "%" را همانگونه که در systemd.unit(5) شرح داده شده است میپذیرد.
آرگومانی که صرفاً شامل ";" باشد باید فرار داده شود (escape شود)، یعنی به صورت "\;" مشخص گردد.
جایگزینی پایهای متغیرهای محیطی پشتیبانی میشود. از "${FOO}" به عنوان بخشی از یک کلمه، یا به عنوان کلمهای مستقل، در خط فرمان استفاده کنید، که در این صورت پاک شده و با مقدار دقیق متغیر محیطی (در صورت وجود) شامل تمام فاصلههای خالی موجود در آن جایگزین میشود، که همیشه دقیقاً منجر به یک آرگومان واحد میگردد. از "$FOO" به عنوان یک کلمه جداگانه در خط فرمان استفاده کنید، که در این صورت با مقدار متغیر محیطی که در فاصلههای خالی تقسیم شده است جایگزین میشود، که منجر به صفر یا چند آرگومان خواهد شد. برای این نوع بسط، نقلقولها هنگام تقسیم به کلمات رعایت شده و پس از آن حذف میشوند.
مثال:
Environment="ONE=one" 'TWO=two two'
ExecStart=echo $ONE $TWO ${TWO}
این دستور /bin/echo را با چهار آرگومان اجرا میکند: "one"، "two"، "two" و "two two".
مثال:
Environment=ONE='one' "TWO='two &two' &too" THREE=
ExecStart=/bin/echo ${ONE} ${TWO} ${THREE}
ExecStart=/bin/echo $ONE $TWO $THREE
این منجر به این میشود که /bin/echo دو بار فراخوانی شود، بار اول با آرگومانهای "'one'"، "'two &two' &too"، ""، و بار دوم با آرگومانهای "one"، "two &two"، "too".
مگر برای دستوراتی با پیشوند اجرایی ویژه ":"، برای ارسال علامت دلار واقعی، از "$$" استفاده کنید. متغیرهایی که مقدار آنها در زمان بسط مشخص نیست به عنوان رشتههای خالی در نظر گرفته میشوند. توجه داشته باشید که آرگومان اول (یعنی برنامهای که باید اجرا شود) نمیتواند یک متغیر باشد.
متغیرهایی که به این شیوه استفاده میشوند ممکن است از طریق Environment= و EnvironmentFile= تعریف شوند. علاوه بر این، متغیرهای فهرستشده در بخش "متغیرهای محیطی در فرآیندهای ایجادشده" در systemd.exec(5) که به عنوان "پیکربندی ایستا" تلقی میشوند، ممکن است استفاده شوند (این شامل مواردی چون $USER میشود، اما نه $TERM).
توجه داشته باشید که خطوط فرمان شل مستقیماً پشتیبانی نمیشوند. اگر قرار است خطوط فرمان شل استفاده شوند، باید به صورت صریح به یک پیادهسازی شل ارسال گردند. مثال:
ExecStart=sh -c 'dmesg | tac'
مثال:
ExecStart=echo one ExecStart=echo "two two"
این دستور echo را دو بار اجرا میکند، هر بار با یک آرگومان: به ترتیب "one" و "two two". از آنجا که دو دستور مشخص شده است، Type=oneshot باید استفاده شود.
مثال:
Type=oneshot ExecStart=:echo $USER ExecStart=-false ExecStart=+:@true $TEST
این دستور /usr/bin/echo را با آرگومان واقعی "$USER" (":" بسط متغیر را لغو میکند)، و سپس /usr/bin/false (مقدار بازگشتی نادیده گرفته میشود زیرا "-" بررسی مقدار بازگشتی را غیرفعال میکند)، و /usr/bin/true (با امتیازات ارتقایافته، با "$TEST" به عنوان argv[0]) را اجرا خواهد کرد.
مثال:
ExecStart=echo / >/dev/null & \; \ ls
این دستور echo را با پنج آرگومان اجرا میکند: "/"، ">/dev/null"، "&"، ";" و "ls".
مثالها (EXAMPLES)
مثال ۳. سرویس ساده (Simple)
فایل واحد زیر سرویسی ایجاد میکند که /usr/sbin/foo-daemon را اجرا خواهد کرد. از آنجا که هیچ Type= مشخص نشده است، پیشفرض Type=simple فرض خواهد شد. systemd فرض میکند که واحد بلافاصله پس از شروع اجرای برنامه آغاز شده است.
[Unit] Description=Foo [Service] ExecStart=/usr/sbin/foo-daemon [Install] WantedBy=multi-user.target
توجه داشته باشید که systemd در اینجا فرض میکند فرآیندی که توسط systemd شروع شده است تا زمانی که سرویس خاتمه یابد به اجرای خود ادامه میدهد. اگر برنامه خود را دیمن میکند (یعنی fork میکند)، لطفاً در عوض از Type=forking استفاده کنید.
از آنجا که هیچ ExecStop= مشخص نشده است، systemd سیگنال SIGTERM و پس از یک مهلت زمانی همچنین SIGKILL را به تمام فرآیندهای شروعشده از این سرویس ارسال خواهد کرد. این رفتار را میتوان تغییر داد، برای جزئیات به systemd.kill(5) مراجعه کنید.
توجه داشته باشید که این نوع واحد شامل هیچ نوع اعلانی در هنگام تکمیل مقداردهی اولیه سرویس نیست. برای این منظور، باید از انواع دیگر واحد استفاده کنید، مانند Type=notify/Type=notify-reload اگر سرویس پروتکل اعلان systemd را درک میکند، Type=forking اگر سرویس میتواند خود را در پسزمینه قرار دهد یا Type=dbus اگر واحد پس از تکمیل مقداردهی اولیه یک نام DBus به دست میآورد. به زیر مراجعه کنید.
مثال ۴. سرویس یکباره (Oneshot)
گاهی اوقات، واحدها باید فقط یک عمل را بدون نگه داشتن فرآیندهای فعال اجرا کنند، مانند بررسی سیستم فایل یا عملیات پاکسازی در هنگام بوت. برای این منظور، Type=oneshot وجود دارد. واحدهای این نوع منتظر میمانند تا فرآیند مشخصشده خاتمه یابد و سپس به وضعیت غیرفعال بازگردند. واحد زیر یک عملیات پاکسازی را انجام میدهد:
[Unit] Description=Cleanup old Foo data [Service] Type=oneshot ExecStart=/usr/sbin/foo-cleanup [Install] WantedBy=multi-user.target
توجه داشته باشید که systemd واحد را تا زمان خاتمه برنامه در وضعیت "starting" در نظر میگیرد، بنابراین وابستگیهای ترتیببندیشده قبل از شروع خود منتظر پایان برنامه میمانند. واحد پس از انجام اجرا به وضعیت "inactive" بازمیگردد و هرگز به وضعیت "active" نمیرسد. این بدان معناست که یک درخواست دیگر برای شروع واحد، عملیات را مجدداً انجام خواهد داد.
واحدهای Type=oneshot تنها واحدهای سرویسی هستند که ممکن است بیش از یک ExecStart= برای آنها مشخص شده باشد. برای واحدهایی با چندین دستور (Type=oneshot)، تمام دستورات دوباره اجرا خواهند شد.
برای Type=oneshot، مقادیر Restart=always و Restart=on-success مجاز نیستند.
مثال ۵. سرویس یکباره قابل توقف
مشابه سرویسهای oneshot، گاهی اوقات واحدهایی وجود دارند که باید برنامهای را برای راهاندازی چیزی اجرا کنند و سپس برنامه دیگری را برای خاموش کردن آن اجرا نمایند، اما هیچ فرآیندی در حالی که آنها "شروعشده" تلقی میشوند فعال باقی نمیماند. پیکربندی شبکه گاهی میتواند در این دسته قرار گیرد. مورد کاربرد دیگر زمانی است که یک سرویس oneshot نباید هر بار که به عنوان یک وابستگی فراخوانی میشود اجرا گردد، بلکه فقط بار اول اجرا شود.
برای این منظور، systemd تنظیم RemainAfterExit=yes را میشناسد، که باعث میشود در صورت خروج موفقیتآمیز عملیات شروع، systemd واحد را فعال در نظر بگیرد. این دستورالعمل میتواند با تمام انواع استفاده شود، اما با Type=oneshot و Type=simple بیشترین کاربرد را دارد. با Type=oneshot، systemd تا زمانی که عملیات شروع تکمیل نشود منتظر میماند و سپس واحد را فعال تلقی میکند، بنابراین وابستگیها تنها پس از موفقیت عملیات شروع آغاز میشوند. با Type=simple، وابستگیها بلافاصله پس از اعزام عملیات شروع آغاز خواهند شد. واحد زیر مثالی برای یک دیوار آتش ایستای ساده ارائه میدهد.
[Unit] Description=Simple firewall [Service] Type=oneshot RemainAfterExit=yes ExecStart=/usr/local/sbin/simple-firewall-start ExecStop=/usr/local/sbin/simple-firewall-stop [Install] WantedBy=multi-user.target
از آنجا که پس از خروج اقدام شروع، واحد در حال اجرا در نظر گرفته میشود، فراخوانی مجدد systemctl start روی آن واحد باعث انجام هیچ اقدامی نخواهد شد.
مثال ۶. سرویسهای سنتی Forking
بسیاری از دیمنها/سرویسهای سنتی هنگام شروع خود را در پسزمینه قرار میدهند (یعنی fork و daemonize میکنند). برای پشتیبانی از این حالت عملکرد، Type=forking را در فایل واحد سرویس تنظیم کنید. systemd تا زمانی که برنامه اصلی هنوز در حال اجرا است سرویس را در مرحله مقداردهی اولیه در نظر میگیرد. هنگامی که با موفقیت خارج شد و حداقل یک فرآیند باقی ماند (و RemainAfterExit=no)، سرویس شروعشده تلقی میشود.
اغلب، یک دیمن سنتی تنها از یک فرآیند تشکیل شده است. بنابراین، اگر پس از خاتمه فرآیند اصلی تنها یک فرآیند باقی بماند، systemd آن فرآیند را فرآیند اصلی سرویس تلقی میکند. در این صورت، متغیر $MAINPID در ExecReload=، ExecStop= و غیره در دسترس خواهد بود.
در صورتی که بیش از یک فرآیند باقی بماند، systemd قادر به تعیین فرآیند اصلی نخواهد بود، بنابراین فرضی در مورد وجود آن نخواهد داشت. در این حالت، $MAINPID به چیزی بسط نمییابد. با این حال، اگر فرآیند تصمیم بگیرد یک فایل PID سنتی بنویسد، systemd قادر خواهد بود PID اصلی را از آنجا بخواند. لطفاً PIDFile= را مطابق با آن تنظیم کنید. توجه داشته باشید که دیمن باید این فایل را قبل از پایان مقداردهی اولیه خود بنویسد. در غیر این صورت، systemd ممکن است قبل از وجود فایل سعی در خواندن آن داشته باشد.
مثال زیر دیمن سادهای را نشان میدهد که انشعاب مییابد و صرفاً یک فرآیند را در پسزمینه شروع میکند:
[Unit] Description=My Simple Daemon [Service] Type=forking ExecStart=/usr/sbin/my-simple-daemon -d [Install] WantedBy=multi-user.target
لطفاً برای جزئیات در مورد چگونگی تأثیرگذاری بر نحوه خاتمه سرویس توسط systemd، systemd.kill(5) را ببینید.
مثال ۷. سرویسهای DBus
برای سرویسهایی که نامی را روی گذرگاه سیستم DBus به دست میآورند، از Type=dbus استفاده کنید و BusName= را متناسب با آن تنظیم نمایید. سرویس نباید fork (daemonize) کند. systemd پس از تصاحب نام در گذرگاه سیستم، سرویس را مقداردهیشده تلقی خواهد کرد. مثال زیر یک سرویس معمولی DBus را نشان میدهد:
[Unit] Description=Simple DBus Service [Service] Type=dbus BusName=org.example.simple-dbus-service ExecStart=/usr/sbin/simple-dbus-service [Install] WantedBy=multi-user.target
برای سرویسهای bus-activatable، بخش [Install] را در فایل سرویس systemd قرار ندهید، بلکه از گزینه SystemdService= در فایل سرویس DBus مربوطه استفاده کنید، برای مثال (/usr/share/dbus-1/system-services/org.example.simple-dbus-service.service):
[D-BUS Service] Name=org.example.simple-dbus-service Exec=/usr/sbin/simple-dbus-service User=root SystemdService=simple-dbus-service.service
لطفاً برای جزئیات در مورد چگونگی تأثیرگذاری بر نحوه خاتمه سرویس توسط systemd، systemd.kill(5) را ببینید.
مثال ۸. سرویسهایی که مقداردهی اولیه خود را به systemd اعلان میکنند
نوشتن سرویسهای Type=simple بسیار آسان است، اما این عیب بزرگ را دارند که systemd نمیتواند تشخیص دهد چه زمانی مقداردهی اولیه سرویس دادهشده کامل شده است. به همین دلیل، systemd از یک پروتکل اعلان ساده پشتیبانی میکند که به دیمنها اجازه میدهد systemd را از اتمام مقداردهی اولیه خود مطلع کنند. برای این منظور از Type=notify یا Type=notify-reload استفاده کنید. یک فایل سرویس معمولی برای چنین دیمنی به شکل زیر خواهد بود:
[Unit] Description=Simple Notifying Service [Service] Type=notify-reload ExecStart=/usr/sbin/simple-notifying-service [Install] WantedBy=multi-user.target
توجه داشته باشید که دیمن باید از پروتکل اعلان systemd پشتیبانی کند، در غیر این صورت systemd فکر میکند سرویس هنوز شروع نشده است و پس از یک مهلت زمانی آن را میکشد. برای مثالی از نحوه بهروزرسانی دیمنها جهت پشتیبانی شفاف از این پروتکل، به sd_notify(3) نگاهی بیندازید. systemd واحد را تا زمانی که اعلان آمادگی دریافت شود در وضعیت 'starting' تلقی میکند.
لطفاً برای جزئیات در مورد چگونگی تأثیرگذاری بر نحوه خاتمه سرویس توسط systemd، systemd.kill(5) را ببینید.
برای جلوگیری از تکرار کد، ترجیح داده میشود در صورت امکان از sd_notify(3) استفاده شود، بهویژه زمانی که سایر APIهای ارائهشده توسط libsystemd(3) نیز استفاده میشوند، اما توجه داشته باشید که پروتکل اعلان بسیار ساده است و طبق Promise پایداری و قابلیت حمل واسط[4] تضمین شده است که پایدار باشد، بنابراین میتواند توسط سرویسها بدون هیچگونه وابستگی خارجی بازپیادهسازی شود. برای یک مثال مستقل، به sd_notify(3) مراجعه کنید.
همچنین ببینید (SEE ALSO)
systemd(1), systemctl(1), systemd-system.conf(5), systemd.unit(5), systemd.exec(5), systemd.resource-control(5), systemd.kill(5), systemd.directives(7), systemd-run(1)
یادداشتها (NOTES)
- 1.
- File Descriptor Store
- 2.
- USB FunctionFS
- 3.
- Control Group v2
- 4.
- Interface Portability and Stability Promise
| systemd 257.13 |