table of contents
| SYSTEMD.SERVICE(5) | systemd.service | SYSTEMD.SERVICE(5) |
الاسم¶
systemd.service - ضبط وحدة الخدمة
موجز¶
service.service
الوصف¶
ملف ضبط الوحدة الذي ينتهي اسمه بـ ".service" يرمز معلومات عن عملية يتحكم فيها systemd ويشرف عليها.
تدرج صفحة الدليل هذه خيارات الضبط الخاصة بنوع هذه الوحدة. راجع systemd.unit(5) للخيارات المشتركة لجميع ملفات ضبط الوحدات. تضبط عناصر الضبط المشتركة في القسمين العامين [Unit] و [Install]. وتضبط خيارات الضبط الخاصة بالخدمة في قسم [Service].
تدرج خيارات إضافية في systemd.exec(5)، والتي تحدد بيئة التنفيذ التي تنفذ فيها الأوامر، وفي systemd.kill(5)، والتي تحدد الطريقة التي تنهى بها عمليات الخدمة، وفي systemd.resource-control(5)، والتي تضبط إعدادات التحكم في الموارد لعمليات الخدمة.
يسمح الأمر systemd-run(1) بإنشاء وحدات .service و .scope آليًا وعابرًا من سطر الأوامر.
قوالب الخدمة¶
يمكن لخدمات systemd أن تأخذ معاملًا واحدًا عبر صيغة "service@argument.service". تسمى هذه الخدمات خدمات "مجسدة"، بينما يسمى تعريف الوحدة بدون معامل argument بـ "القالب". يمكن أن يكون المثال قالب الخدمة dhcpcd@.service الذي يأخذ واجهة شبكة كمعامل لتشكيل خدمة مجسدة. داخل ملف الخدمة، يمكن الوصول إلى هذا المعامل أو "اسم التجسيد" باستخدام محددات %. راجع systemd.unit(5) للتفاصيل.
اعتمادات آلية¶
التبعيات الضمنية¶
تُضاف التبعيات التالية ضمنيًا:
قد تُضاف اعتماديات ضمنية إضافية نتيجةً لمعاملات التنفيذ والتحكم في الموارد كما وُثقت في systemd.exec(5) و systemd.resource-control(5).
الاعتمادات المبدئية¶
تُضاف الاعتماديات التالية ما لم يُضبط DefaultDependencies=no:
الخيارات¶
قد تتضمن ملفات وحدات الخدمة قسمي [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. تُعتبر وحدة الخدمة من هذا النوع في حالة التنشيط حتى يُستحوذ على اسم الناقل المحدد. وتُعتبر منشطة طالما أن اسم الناقل مأخوذ. وبمجرد تحرير اسم الناقل، تُعتبر الخدمة غير صالحة للعمل مما يؤدي إلى محاولة مدير الخدمة إنهاء أي عمليات متبقية تنتمي للخدمة. وبالتالي ينبغي للخدمات التي تتخلى عن اسم ناقلها كجزء من منطق إيقاف تشغيلها أن تكون مستعدة لتلقي إشارة SIGTERM (أو أي إشارة مضبطة في KillSignal=) نتيجة لذلك.
إذا كانت الخدمة تدعم إعادة التحميل، وتستخدم إشارة لبدء إعادة التحميل، فيوصى باستخدام 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() أو واجهة برمجة تطبيقات مكافئة بواسطة الخدمة في الوقت المناسب) — وإذا لم تكن مدعومة، فإن forking هو البديل: حيث يدعم بروتوكول بدء تشغيل خدمات UNIX التقليدي الثقيل. لاحظ أن استخدام أي نوع آخر غير simple قد يؤخر عملية بدء التشغيل، حيث يحتاج مدير الخدمة إلى انتظار اكتمال بعض تهيئات الخدمة على الأقل. (لاحظ أيضًا أنه لا يوصى عمومًا باستخدام idle أو oneshot للخدمات طويلة التشغيل.)
لاحظ أن إعدادات الخدمة المختلفة (مثل User= و Group= من خلال libc NSS) قد تؤدي إلى استدعاءات IPC حاجزة "مخفية" لخدمات أخرى عند استخدامها. في بعض الأحيان قد يكون من المستحسن استخدام نوع الخدمة simple لضمان عدم تأثر منطق معاملات مدير الخدمة بمثل هذه العمليات البطيئة المحتملة والاعتماديات المخفية، لأن هذا هو نوع الخدمة الوحيد الذي لن ينتظر فيه مدير الخدمة اكتمال عمليات إعداد تنفيذ الخدمة هذه قبل المتابعة.
ExitType=
يوصى عمومًا باستخدام 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= برمز خروج من 1 إلى 254 (شاملاً)، تُتخطى الأوامر المتبقية ولا تُعلم الوحدة كفاشلة. ومع ذلك، إذا خرج أمر ExecCondition= برمز 255 أو بشكل غير طبيعي (مثل انتهاء المهلة، أو القضاء عليه بإشارة، إلخ)، ستُعتبر الوحدة فاشلة (وستُتخطى الأوامر المتبقية). رمز الخروج 0 أو الرموز التي تطابق SuccessExitStatus= ستواصل التنفيذ إلى الأوامر التالية.
تنطبق نفس التوصيات بشأن عدم تشغيل عمليات طويلة التشغيل في ExecStartPre= أيضًا على ExecCondition=. سيقوم ExecCondition= أيضًا بتشغيل الأوامر في ExecStopPost=، كجزء من إيقاف الخدمة، في حال حدوث أي خروج غير صفري أو غير طبيعي، مثل تلك الموصوفة أعلاه.
أُضيف في الإصدار 243.
ExecReload=
يُضبط متغير بيئة إضافي وخاص: إذا كان معروفًا، يُضبط $MAINPID على العملية الرئيسة للعفريت، ويمكن استخدامه لأسطر أوامر مثل التالي:
ExecReload=kill -HUP $MAINPID
لاحظ مع ذلك أن إعادة تحميل عفريت عن طريق إدراج إشارة في الطابور دون إشعار بالاكتمال (كما هو الحال مع السطر المثالي أعلاه) ليس خيارًا جيدًا عادةً، لأن هذه عملية غير متزامنة وبالتالي فهي غير مناسبة عند ترتيب إعادات تحميل خدمات متعددة ضد بعضها البعض. لذا يوصى بشدة إما باستخدام Type=notify-reload، أو ضبط ExecReload= على أمر لا يطلق فقط إعادة تحميل ضبط العفريت، بل ينتظر أيضًا بشكل متزامن اكتماله. على سبيل المثال، يستخدم dbus-broker(1) التالي:
ExecReload=busctl call org.freedesktop.DBus \
/org/freedesktop/DBus org.freedesktop.DBus \
ReloadConfig
يمكن دمج هذا الإعداد مع Type=notify-reload، وفي هذه الحالة تُرسل الإشارة إلى العملية الرئيسة للخدمة بعد انتهاء تنفيذ جميع أسطر الأوامر المحددة. وعلى وجه الخصوص، إذا استُقبل إشعار "RELOADING=1" قبل اكتمال ExecReload=، فيتُخطى إرسال الإشارة ويبدأ مدير الخدمة فورًا في الاستماع لـ "READY=1".
ExecReloadPost=
أُضيف في الإصدار 259.
ExecStop=
لاحظ أنه لا يكفي عادةً تحديد أمر لهذا الإعداد يطلب فقط من الخدمة الإنهاء (على سبيل المثال، عن طريق إرسال شكل من أشكال إشارة الإنهاء إليها)، ولكنه لا ينتظر قيامها بذلك. نظرًا لأن العمليات المتبقية للخدمات تُقضى عليها وفقًا لـ KillMode= و KillSignal= أو RestartKillSignal= كما هو موصوف أعلاه فور خروج الأمر، فقد لا يؤدي هذا إلى إيقاف نظيف. لذا ينبغي أن يكون الأمر المحدد عملية متزامنة، وليس عملية غير متزامنة.
لاحظ أن الأوامر المحددة في ExecStop= لا تُنفذ إلا عندما تبدأ الخدمة بنجاح أولاً. ولا تُستدعى إذا لم تُبدأ الخدمة أصلاً، أو في حال فشل بدء تشغيلها، على سبيل المثال لأن أيًا من الأوامر المحددة في ExecStart=، أو ExecStartPre=، أو ExecStartPost= قد فشل (ولم يكن مسبوقًا بـ "-"، انظر أعلاه) أو انتهت مهلته. استخدم ExecStopPost= لاستدعاء الأوامر عندما تفشل الخدمة في بدء التشغيل بشكل صحيح وتُغلق مجددًا. لاحظ أيضًا أن عملية الإيقاف تُنفذ دائمًا إذا بدأت الخدمة بنجاح، حتى لو انتهت العمليات في الخدمة من تلقاء نفسها أو قُضي عليها. يجب أن تكون أوامر الإيقاف مستعدة للتعامل مع تلك الحالة. سيُبطل ضبط $MAINPID إذا علم systemd أن العملية الرئيسة قد خرجت بحلول وقت استدعاء أوامر الإيقاف.
تُنفذ طلبات إعادة تشغيل الخدم كعمليات إيقاف تليها عمليات بدء. هذا يعني أن ExecStop= و ExecStopPost= يُنفذان أثناء عملية إعادة تشغيل الخدمة.
يوصى باستخدام هذا الإعداد للأوامر التي تتواصل مع الخدمة طالبةً إنهاءً نظيفًا. لخطوات التنظيف بعد الوفاة، استخدم ExecStopPost= بدلاً من ذلك.
ExecStopPost=
يوصى باستخدام هذا الإعداد لعمليات التنظيف التي يجب تنفيذها حتى عندما تفشل الخدمة في بدء التشغيل بشكل صحيح. يجب أن تكون الأوامر المضبطة بهذا الإعداد قادرة على العمل حتى لو فشلت الخدمة في بدء التشغيل في منتصف الطريق وتركت بيانات ملوثة غير مكتملة التهيئة من حولها. ونظراً لأن عمليات الخدمة قد خرجت بالفعل على الأرجح عند تنفيذ الأوامر المحددة بهذا الإعداد، فلا ينبغي لها محاولة الاتصال بها.
لاحظ أن جميع الأوامر المضبطة بهذا الإعداد تُستدعى مع رمز نتيجة الخدمة، بالإضافة إلى رمز خروج وحالة العملية الرئيسة، المضبطة في متغيرات البيئة $SERVICE_RESULT و $EXIT_CODE و $EXIT_STATUS، راجع systemd.exec(5) للتفاصيل.
لاحظ أن تنفيذ ExecStopPost= يُؤخذ في الحسبان لغرض قيود الترتيب Before=/After=.
RestartSec=
RestartSteps=
مثال:
RestartSec=10s RestartSteps=4 RestartMaxDelaySec=160s
سيؤدي هذا إلى إنتاج فترات إعادة التشغيل التالية: 10ث، 20ث، 40ث، 80ث، 160ث، 160ث، 160ث، إلخ. لاحظ الاستكمال الهندسي والنسبة الثابتة الناتجة بين الفترات؛ وهي هنا 2. صيغة الـ 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 مَرفوضان لها.
جدول 1. أسباب
الخروج
وتأثير
إعدادات Restart=
| إعدادات إعادة التشغيل/أسباب الخروج | no | always | on-success | on-failure | on-abnormal | on-abort | on-watchdog |
| رمز خروج أو إشارة نظيفة | X | X | |||||
| رمز خروج غير نظيف | X | X | |||||
| إشارة غير نظيفة | X | X | X | X | |||
| المهلة | X | X | X | ||||
| مراقب الجرأة | X | X | X | X | |||
| الإنهاء بسبب نفاد الذاكرة (OOM) | 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")، وهكذا. إنه يتحكم فقط فيما يحدث كتأثير لحالات الخروج هذه، وكيف ينتشر ذلك إلى حالة الخدمة ككل.
قد يظهر هذا الخيار أكثر من مرة، وفي هذه الحالة تُدمج قائمة حالات الخروج الناجحة. إذا عُينت سلسلة فارغة لهذا الخيار، فستُعاد تهيئة القائمة، ولن يكون لجميع التعيينات السابقة لهذا الخيار أي تأثير.
مثال 1. خدمة مع إعداد SuccessExitStatus=
SuccessExitStatus=TEMPFAIL 250 SIGKILL
تُعتبر حالة الخروج 75 (TEMPFAIL)، و 250، وإشارة الإنهاء SIGKILL إنهاءات خدمة نظيفة.
ملاحظة: يمكن استخدام systemd-analyze exit-status لسرد حالات الخروج والترجمة بين قيم الحالة الرقمية والأسماء.
أُضيف في الإصدارة 189.
RestartPreventExitStatus=
قد يظهر هذا الخيار أكثر من مرة، وفي هذه الحالة تُدمج قائمة الحالات المانعة لإعادة التشغيل. إذا عُينت سلسلة فارغة لهذا الخيار، فستُعاد تهيئة القائمة ولن يكون لجميع التعيينات السابقة لهذا الخيار أي تأثير.
لاحظ أن هذا الإعداد ليس له أي تأثير على العمليات المهيأة عبر 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() قد تُنسب إلى الوحدات بشكل صحيح فقط إذا كانت العملية المرسلة لا تزال موجودة في الوقت الذي تعالج فيه العملية ذات المعرف 1 (PID 1) الرسالة، أو إذا كانت العملية المرسلة مُتتبعة صراحةً في وقت التشغيل بواسطة مدير الخدمة. الحالة الأخيرة تكون عندما يفرع مدير الخدمة العملية في الأصل، أي في جميع العمليات التي تطابق main أو exec. بالمقابل، إذا أرسلت عملية مساعدة للوحدة رسالة sd_notify() وخرجت فورًا، فقد لا يتمكن مدير الخدمة من نسبة الرسالة بشكل صحيح إلى الوحدة، وبالتالي سيتجاهلها، حتى لو ضُبط NotifyAccess=all لها.
وبالتالي، للتخلص من جميع شروط السباق التي تنطوي على البحث عن وحدة العميل ونسبة الإشعارات إلى الوحدات بشكل صحيح، يمكن استخدام sd_notify_barrier(). يعمل هذا الاستدعاء كنقطة تزامن ويضمن أن جميع الإشعارات المرسلة قبل هذا الاستدعاء قد التُقطت بواسطة مدير الخدمة عندما يعود بنجاح. يلزم استخدام sd_notify_barrier() للعملاء الذين لا يستدعيهم مدير الخدمة، وإلا فإن آلية التزامن هذه غير ضرورية لنسبة الإشعارات إلى الوحدة.
Sockets=
لاحظ أن واصفات ملفات المقبس نفسها قد تُمرر إلى عمليات متعددة في وقت واحد. لاحظ أيضًا أنه قد تُنشط خدمة مختلفة عند حركة مرور المقبس الواردة عن تلك الخدمة المهيأة في النهاية لوراثة واصفات ملفات المقبس. أو بعبارة أخرى: إعداد Service= لوحدات .socket لا يجب أن يطابق عكس إعداد Sockets= لـ .service التي يشير إليها.
قد يظهر هذا الخيار أكثر من مرة، وفي هذه الحالة تُدمج قائمة وحدات المقابس. لاحظ أنه بمجرد ضبطه، فإن مسح قائمة المقابس مرة أخرى (على سبيل المثال، عن طريق تعيين سلسلة فارغة لهذا الخيار) غير مدعوم.
FileDescriptorStoreMax=
يمكن استخدام أمر fdstore لـ systemd-analyze(1) لسرد المحتويات الحالية لمخزن واصف الملفات الخاص بالخدمة.
لاحظ أن مدير الخدمة سيمرر فقط واصفات الملفات الموجودة في مخزن واصف الملفات إلى العمليات الخاصة بالخدمة نفسها، ولن يمررها أبدًا إلى عملاء آخرين عبر IPC أو ما شابه. ومع ذلك، فإنه يسمح للعملاء غير المتميزين بالاستعلام عن قائمة واصفات الملفات المفتوحة حالياً للخدمة. وبالتالي يمكن وضع البيانات الحساسة بأمان داخل الملفات المشار إليها، ولكن لا ينبغي إرفاقها بالبيانات الوصفية (مثل تضمينها في أسماء الملفات) لواصفات الملفات المخزنة.
إذا ضُبط هذا الخيار على قيمة غير صفرية، فسيُضبط متغير البيئة $FDSTORE للعمليات المستدعاة لهذه الخدمة. انظر systemd.exec(5) للتفاصيل.
لمزيد من المعلومات حول مخزن واصف الملفات، انظر نظرة عامة على مخزن واصف الملفات[1].
أُضيف في الإصدارة 219.
FileDescriptorStorePreserve=
استخدم أمر systemctl clean --what=fdstore ... لتحرير مخزن واصف الملفات صراحةً.
أُضيف في الإصدار 254.
USBFunctionDescriptors=
أُضيف في الإصدارة 227.
USBFunctionStrings=
أُضيف في الإصدارة 227.
OOMPolicy=
يأخذ هذا الإعداد أحد الخيارات continue أو stop أو kill. إذا ضُبط على continue وقُتلت عملية في الوحدة بواسطة قاتل نفاد الذاكرة (OOM killer)، يُسجل هذا في السجل ولكن تستمر الوحدة في العمل. إذا ضُبط على stop، يُسجل الحدث وتُنهى عمليات الوحدة نظيفًا بواسطة مدير الخدمة. إذا ضُبط على kill وقُتلت إحدى عمليات الوحدة بواسطة قاتل نفاد الذاكرة، تُوجَّه النواة لقتل جميع العمليات المتبقية للوحدة أيضًا، عن طريق ضبط السمة memory.oom.group على القيمة 1؛ انظر أيضًا صفحة النواة مجموعة التحكم الإصدار الثاني Control Group v2[3]. في حالة كل من stop و kill، تنتهي الخدمة في النهاية في حالة الفشل oom-kill وبعد ذلك قد يُطبق الإعداد Restart=.
يُضبط مبدئياً على الإعداد 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.
RefreshOnReload=
على وجه الخصوص، إذا ضُبط هذا الخيار صراحةً، وكانت الموارد المعنية قيد الاستخدام، فقد تُعاد تحميل الخدمة دون أي آلية إعادة تحميل فعلية (ExecReload= أو Type=notify-reload) لإخطار العملية الرئيسة، وفي هذه الحالة تُعتبر إعادة التحميل مكتملة فورًا بعد الإنعاش.
أُضيف في الإصدار 260.
تحقق من systemd.unit(5)، و systemd.exec(5)، و systemd.kill(5) لمزيد من الإعدادات.
سطور الأوامر¶
يصف هذا القسم تحليل سطر الأوامر واستبدالات المتغيرات والمحددات لخيارات ExecStart=، و ExecStartPre=، و ExecStartPost=، و ExecReload=، و ExecStop=، و ExecStopPost=، و ExecCondition=.
يمكن تحديد سطور أوامر متعددة باستخدام الضبط ذي الصلة عدة مرات.
تُزال علامات الاقتباس من كل سطر أوامر باستخدام القواعد الموصوفة في قسم "Quoting" في systemd.syntax(7). يصبح العنصر الأول هو الأمر المراد تنفيذه، والعناصر اللاحقة هي الوسائط.
هذه الصيغة مستوحاة من صيغة الصدفة، ولكن لا تُفهم سوى المحارف الفوقية والتوسيعات الموصوفة في الفقرات التالية، وتوسيع المتغيرات مختلف. على وجه التحديد، إعادة التوجيه باستخدام "<" و "<<" و ">" و ">>"، والأنابيب باستخدام "|"، وتشغيل البرامج في الخلفية باستخدام "&"، والعناصر الأخرى لصيغة الصدفة غير مدعومة.
يمكن أن يحتوي الأمر المراد تنفيذه على مسافات، ولكن محارف التحكم غير مسموح بها.
يمكن أن يُسبق كل أمر بعدد من المحارف الخاصة:
الجدول 2. بادئات
الملفات
التنفيذية
الخاصة
| البادئة | التأثير |
| "@" | إذا سُبق مسار الملف التنفيذي بـ "@"، فستُمرّر العلامة الثانية المحددة كـ argv[0] إلى العملية المنفّذة (بدلاً من اسم الملف الفعلي)، متبوعة بالوسائط الإضافية المحددة، ما لم يُحدّد "|" أيضًا، وفي هذه الحالة يُمكّن دلالات صدفة الولوج للصدفة المولّدة عن طريق إلحاق بادئة "-" بـ argv[0]. |
| "-" | إذا سُبق مسار الملف التنفيذي بـ "-"، فإن رمز خروج الأمر الذي يُعتبر عادةً فشلاً (أي حالة خروج غير صفرية أو خروج غير طبيعي بسبب إشارة) يُسجّل، ولكن ليس له تأثير آخر ويُعتبر مكافئًا للنجاح. |
| ":" | إذا سُبق مسار الملف التنفيذي بـ ":"، فلن يُطبّق استبدال متغير البيئة (كما هو موصوف أسفل هذا الجدول). |
| "+" | إذا سُبق مسار الملف التنفيذي بـ "+" فستُنفّذ العملية بامتيازات كاملة. في هذا الوضع، لا تُطبّق قيود الامتيازات المضبوطة بـ User= أو Group= أو CapabilityBoundingSet= أو خيارات مساحات أسماء نظام الملفات المختلفة (مثل PrivateDevices= و PrivateTmp=) على سطر الأوامر المستدعى (ولكنها لا تزال تؤثر على أي سطور ExecStart= و ExecStop= و ... أخرى). ومع ذلك، لاحظ أن هذا لن يتجاوز الخيارات التي تنطبق على مجموعة التحكم بأكملها، مثل DevicePolicy=، انظر systemd.resource-control(5) للقائمة الكاملة. |
| "!" | على غرار المحرف "+" المناقش أعلاه، يتيح هذا استدعاء سطور الأوامر بامتيازات مرتفعة. ومع ذلك، على عكس "+"، فإن المحرف "!" يغير حصريًا تأثير User= و Group= و SupplementaryGroups=، أي المقاطع التي تؤثر على اعتمادات المستخدم والمجموعة فقط. لاحظ أنه يمكن دمج هذا الضبط مع DynamicUser=، وفي هذه الحالة يُخصّص زوج مستخدم/مجموعة ديناميكي قبل استدعاء الأمر، ولكن يُترك تغيير الاعتمادات للعملية المنفّذة نفسها. |
| "|" | إذا حُدّد "|" كمستقل كمسار للملف التنفيذي، فاستدعِ صدفة User= المبدئية. وإذا حُدّد كبادئة، فاستخدم الصدفة ("-c") لتوليد الملف التنفيذي. وعند استخدام "@" بالتزامن مع ذلك، ستُلحق بادئة "-" بـ argv[0] للصدفة لتمكين دلالات صدفة الولوج. |
يمكن استخدام "@" و "|" و "-" و ":" وأحد الخيارين "+"/"!" معًا ويمكن أن تظهر بأي ترتيب. ومع ذلك، لا يمكن تحديد "+" و "!" في الوقت نفسه.
لكل أمر، يجب أن يكون الوسيط الأول إما مسارًا مطلقًا لملف تنفيذي أو اسم ملف بسيط دون أي شرطات مائلة. إذا لم يكن الأمر مسارًا كاملاً (مطلقًا)، فسيُحلّ إلى مسار كامل باستخدام مسار بحث ثابت يُحدّد في وقت التصريف. تشمل الأدلة المبحوث فيها /usr/local/bin/ و /usr/bin/ ونظائرها sbin/ (فقط في الأنظمة التي تستخدم bin/ و sbin/ منفصلين). وبالتالي من الآمن استخدام اسم الملف التنفيذي فقط في حالة الملفات التنفيذية الموجودة في أي من الأدلة "القياسية"، ويجب استخدام مسار مطلق في الحالات الأخرى. تلميح: يمكن الاستعلام عن مسار البحث هذا باستخدام systemd-path search-binaries-default.
يقبل سطر الأوامر محددات "%" كما هو موصوف في systemd.unit(5).
الوسيط الذي يتكون فقط من ";" يجب هروبه، أي يُحدّد كـ "\;".
استبدال متغيرات البيئة الأساسية مدعوم. استخدم "${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=. بالإضافة إلى ذلك، يمكن استخدام المتغيرات المدرجة في قسم "Environment variables in spawned processes" في 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".
أمثلة¶
المثال 3. خدمة بسيطة
ينشئ ملف الوحدة التالي خدمة ستنفذ /usr/sbin/foo-daemon. نظرًا لعدم تحديد أي Type=، سيُفترض الوضع المبدئي Type=simple. سيفترض systemd أن الوحدة قد بُدئت فورًا بعد أن يبدأ البرنامج في التنفيذ.
[Unit] Description=Foo [Service] ExecStart=/usr/sbin/foo-daemon [Install] WantedBy=multi-user.target
لاحظ أن systemd يفترض هنا أن العملية التي بدأها systemd ستستمر في العمل حتى تنتهي الخدمة. إذا قام البرنامج بجدولة نفسه في الخلفية (أي يتفرع)، فيرجى استخدام Type=forking بدلاً من ذلك.
نظرًا لعدم تحديد أي ExecStop=، سيرسل systemd إشارة SIGTERM إلى جميع العمليات التي بدأت من هذه الخدمة، وبعد مهلة زمنية سيرسل أيضًا SIGKILL. يمكن تعديل هذا السلوك، انظر systemd.kill(5) للتفاصيل.
لاحظ أن نوع الوحدة هذا لا يتضمن أي نوع من الإشعارات عندما تكمل الخدمة تهيئتها. لهذا، يجب استخدام أنواع وحدات أخرى، مثل Type=notify/Type=notify-reload إذا كانت الخدمة تفهم بروتوكول إشعارات systemd، أو Type=forking إذا كانت الخدمة يمكنها وضع نفسها في الخلفية أو Type=dbus إذا حصلت الوحدة على اسم DBus بمجرد اكتمال التهيئة. انظر أدناه.
المثال 4. خدمة ذات طلقة واحدة
في بعض الأحيان، ينبغي للوحدات مجرد تنفيذ إجراء دون الإبقاء على عمليات نشطة، مثل فحص نظام ملفات أو إجراء تنظيف عند الإقلاع. لهذا الغرض، يوجد الخيار Type=oneshot. ستنتظر الوحدات من هذا النوع حتى تنتهي العملية المحددة ثم تعود لتصبح غير نشطة. ستقوم الوحدة التالية بإجراء تنظيف:
[Unit] Description=Cleanup old Foo data [Service] Type=oneshot ExecStart=/usr/sbin/foo-cleanup [Install] WantedBy=multi-user.target
لاحظ أن systemd سيعتبر الوحدة في حالة "بدء التشغيل" حتى ينتهي البرنامج، لذا ستنتظر الاعتماديات المرتبة انتهاء البرنامج قبل أن تبدأ هي نفسها. ستعود الوحدة إلى الحالة "غير نشطة" بعد الانتهاء من التنفيذ، دون أن تصل أبدًا إلى الحالة "نشطة". وهذا يعني أن طلبًا آخر لبدء الوحدة سيؤدي إلى تنفيذ الإجراء مجددًا.
وحدات الخدمة من النوع Type=oneshot هي وحدات الخدمة الوحيدة التي يمكن أن يُحدد لها أكثر من ExecStart= واحد. بالنسبة للوحدات ذات الأوامر المتعددة (Type=oneshot)، ستُشغل جميع الأوامر مجددًا.
بالنسبة لـ Type=oneshot، فإن Restart=always و Restart=on-success غير مسموح بهما.
المثال 5. خدمة ذات طلقة واحدة قابلة للإيقاف
على غرار خدمات الطلقة الواحدة، توجد أحيانًا وحدات تحتاج إلى تنفيذ برنامج لإعداد شيء ما ثم تنفيذ برنامج آخر لإغلاقه، ولكن لا تظل أي عملية نشطة بينما تُعتبر "مبدوءة". يمكن أن يقع ضبط الشبكة أحيانًا في هذه الفئة. حالة استخدام أخرى هي إذا كان ينبغي عدم تنفيذ خدمة طلقة واحدة في كل مرة تُسحب فيها كاعتمادية، بل في المرة الأولى فقط.
لهذا، يعرف 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 على تلك الوحدة مجددًا لن يؤدي إلى اتخاذ أي إجراء.
المثال 6. الخدمات المتفرعة التقليدية
تقوم العديد من العفاريت/الخدمات التقليدية بوضع نفسها في الخلفية (أي تتفرع) عند بدء التشغيل. اضبط 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.kill(5) للحصول على تفاصيل حول كيفية التأثير على الطريقة التي ينهي بها systemd الخدمة.
المثال 7. خدمات DBus
بالنسبة للخدمات التي تكتسب اسمًا على ناقل نظام DBus، استخدم Type=dbus واضبط BusName= وفقًا لذلك. لا ينبغي للخدمة أن تتفرع (تتحول لعفريت). سيعتبر 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.kill(5) للحصول على تفاصيل حول كيفية التأثير على الطريقة التي ينهي بها systemd الخدمة.
المثال 8. الخدمات التي تخطر 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 الوحدة في حالة 'بدء التشغيل' حتى يصل إشعار الجاهزية.
يرجى الاطلاع على systemd.kill(5) للحصول على تفاصيل حول كيفية التأثير على الطريقة التي ينهي بها systemd الخدمة.
لتجنب تكرار الكود، يفضل استخدام sd_notify(3) عندما يكون ذلك ممكنًا، خاصة عند استخدام واجهات برمجة التطبيقات الأخرى التي يوفرها libsystemd(3) أيضًا، ولكن لاحظ أن بروتوكول الإشعارات بسيط للغاية ومضمون الاستقرار وفقًا لـ Interface Portability and Stability Promise[4]، لذا يمكن إعادة تطبيقه بواسطة الخدمات دون أي اعتماديات خارجية. للحصول على مثال مكتفٍ بذاته، انظر sd_notify(3).
انظر أيضًا¶
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)
ملاحظات¶
- 1.
- مخزن واصف الملف
- 2.
- نظام ملفات وظائف USB (USB FunctionFS)
- 3.
- مجموعة التحكم النسخة 2
- 4.
- وعد استقرار وقابلية نقل الواجهة
ترجمة¶
تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي <zayed.alsaidi@gmail.com>
هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.
إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: kde-l10n-ar@kde.org.
| systemd 260.1 |