table of contents
- unstable 4.31.0-1
| SYSTEMD-SOFT-REBOOT.SERVICE(8) | systemd-soft-reboot.service | SYSTEMD-SOFT-REBOOT.SERVICE(8) |
الاسم¶
systemd-soft-reboot.service - عملية إعادة تشغيل فضاء المستخدم
موجز¶
systemd-soft-reboot.service
الوصف¶
systemd-soft-reboot.service هي خدمة نظام تُستجلب بواسطة soft-reboot.target وتكون مسؤولة عن تنفيذ عملية إعادة تشغيل خاصة بفضاء المستخدم فقط. عند استدعائها، تُرسل إشارة SIGTERM إلى أي عمليات لا تزال قيد التشغيل (لكنها لا تنتظر خروج العمليات)، وتتبعها بـ SIGKILL. إذا كان الدليل /run/nextroot/ موجودًا (والذي قد يكون دليلًا عاديًا، أو نقطة وصل دليل، أو رابطًا رمزيًا لأي منهما)، فستُحوِّل جذر نظام ملفات إليه. ثم تُعيد تنفيذ مدير الخدمات من نظام ملفات الجذر (ربما الجديد الآن)، مما سيُدرج معاملة إقلاع جديدة كما في إعادة التشغيل العادية.
تسمح عملية إعادة التشغيل الخاصة بفضاء المستخدم فقط هذه بتحديث أو إعادة تعيين كامل فضاء المستخدم مع أقل وقت تعطل، لأن عملية إعادة التشغيل لا تمر عبر:
ومع ذلك، يأتي هذا الشكل من إعادة التشغيل مع عيوب أيضًا:
يمكن معالجة هذه القيود بوسائل متنوعة، وهي خارج نطاق هذه الوثائق، مثل التصحيح المباشر للنواة وملفات /etc/sysctl.d/ الشاملة بما يكفي.
تمرير الموارد¶
يمكن تمرير موارد متنوعة لنظام التشغيل في وقت التشغيل من جلسة نظام إلى التالية، عبر عملية إعادة تشغيل فضاء المستخدم. تحديدًا:
[Unit] Description=My Surviving Service SurviveFinalKillSignal=yes IgnoreOnIsolate=yes DefaultDependencies=no After=basic.target Conflicts=reboot.target kexec.target poweroff.target halt.target rescue.target emergency.target Before=shutdown.target rescue.target emergency.target [Service] Type=oneshot ExecStart=sleep infinity
[Unit] SurviveFinalKillSignal=yes IgnoreOnIsolate=yes DefaultDependencies=no
/* SPDX-License-Identifier: MIT-0 */ /* خدمة D-Bus تُعيد الاتصال آليًا عند إعادة تشغيل ناقل النظام.
*
* جمّع باستخدام 'cc sd_bus_service_reconnect.c $(pkg-config --libs --cflags libsystemd)'
*
* للسماح للبرنامج بامتلاك الاسم 'org.freedesktop.ReconnectExample'،
* أضف ما يلي كـ /etc/dbus-1/system.d/org.freedesktop.ReconnectExample.conf
* ثم أعد تحميل الوسيط باستخدام 'systemctl reload dbus': <?xml version="1.0"?> <!--*-nxml-*--> <!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> <busconfig>
<policy user="root">
<allow own="org.freedesktop.ReconnectExample"/>
<allow send_destination="org.freedesktop.ReconnectExample"/>
<allow receive_sender="org.freedesktop.ReconnectExample"/>
</policy>
<policy context="default">
<allow send_destination="org.freedesktop.ReconnectExample"/>
<allow receive_sender="org.freedesktop.ReconnectExample"/>
</policy> </busconfig>
*
* To get the property via busctl:
*
* $ busctl --user get-property org.freedesktop.ReconnectExample \
* /org/freedesktop/ReconnectExample \
* org.freedesktop.ReconnectExample \
* Example
* s "example"
*/ #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <systemd/sd-bus.h> #define _cleanup_(f) __attribute__((cleanup(f))) static int log_error(int r, const char *str) {
fprintf(stderr, "%s فشل: %s\n", str, strerror(-r));
return r; } typedef struct object {
const char *example;
sd_bus **bus;
sd_event **event; } object; static int property_get(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
object *o = userdata;
if (strcmp(property, "Example") == 0)
return sd_bus_message_append(reply, "s", o->example);
return sd_bus_error_setf(error,
SD_BUS_ERROR_UNKNOWN_PROPERTY,
"خاصية مجهولة '%s'",
property); } /* https://www.freedesktop.org/software/systemd/man/sd_bus_add_object.html */ static const sd_bus_vtable vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY(
"Example", "s",
property_get,
0,
SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_VTABLE_END }; static int setup(object *o); static int on_disconnect(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
int r;
r = setup((object *)userdata);
if (r < 0) {
object *o = userdata;
r = sd_event_exit(*o->event, r);
if (r < 0)
return log_error(r, "sd_event_exit()");
}
return 1; } /* التأكد من خروج حلقة الأحداث بخطأ واضح إذا فشل الحصول على
* اسم الخدمة المعروف */ static int request_name_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
int r;
if (!sd_bus_message_is_method_error(m, NULL))
return 1;
const sd_bus_error *error = sd_bus_message_get_error(m);
if (sd_bus_error_has_names(error, SD_BUS_ERROR_TIMEOUT, SD_BUS_ERROR_NO_REPLY))
return 1; /* الناقل غير متاح، حاول لاحقًا */
fprintf(stderr, "فشل طلب الاسم: %s\n", error->message);
object *o = userdata;
r = sd_event_exit(*o->event, -sd_bus_error_get_errno(error));
if (r < 0)
return log_error(r, "sd_event_exit()");
return 1; } static int setup(object *o) {
int r;
/* إذا كنا نُعيد الاتصال، فيجب إغلاق كائن الناقل وفصله
* من حلقة الأحداث وإعادة إنشائه.
* https://www.freedesktop.org/software/systemd/man/sd_bus_detach_event.html
* https://www.freedesktop.org/software/systemd/man/sd_bus_close_unref.html
*/
if (*o->bus) {
r = sd_bus_detach_event(*o->bus);
if (r < 0)
return log_error(r, "sd_bus_detach_event()");
*o->bus = sd_bus_close_unref(*o->bus);
}
/* أنشئ كائن ناقل جديد لناقل النظام، واضبطه للانتظار حتى يكون
* D-Bus متاحًا بدلاً من الفشل، ثم ابدأ تشغيله. كل العمليات
* التالية غير متزامنة ولن تمنع الانتظار ليكون D-Bus
* متاحًا.
* https://www.freedesktop.org/software/systemd/man/sd_bus_new.html
* https://www.freedesktop.org/software/systemd/man/sd_bus_set_address.html
* https://www.freedesktop.org/software/systemd/man/sd_bus_set_bus_client.html
* https://www.freedesktop.org/software/systemd/man/sd_bus_negotiate_creds.html
* https://www.freedesktop.org/software/systemd/man/sd_bus_set_watch_bind.html
* https://www.freedesktop.org/software/systemd/man/sd_bus_set_connected_signal.html
* https://www.freedesktop.org/software/systemd/man/sd_bus_start.html
*/
r = sd_bus_new(o->bus);
if (r < 0)
return log_error(r, "sd_bus_new()");
r = sd_bus_set_address(*o->bus, "unix:path=/run/dbus/system_bus_socket");
if (r < 0)
return log_error(r, "sd_bus_set_address()");
r = sd_bus_set_bus_client(*o->bus, 1);
if (r < 0)
return log_error(r, "sd_bus_set_bus_client()");
r = sd_bus_negotiate_creds(*o->bus, 1, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS);
if (r < 0)
return log_error(r, "sd_bus_negotiate_creds()");
r = sd_bus_set_watch_bind(*o->bus, 1);
if (r < 0)
return log_error(r, "sd_bus_set_watch_bind()");
r = sd_bus_start(*o->bus);
if (r < 0)
return log_error(r, "sd_bus_start()");
/* انشر واجهة على الناقل، مع تحديد مسار وصول الكائن
* المعروف واسم الواجهة العامة.
* https://www.freedesktop.org/software/systemd/man/sd_bus_add_object.html
* https://dbus.freedesktop.org/doc/dbus-tutorial.html
*/
r = sd_bus_add_object_vtable(*o->bus,
NULL,
"/org/freedesktop/ReconnectExample",
"org.freedesktop.ReconnectExample",
vtable,
o);
if (r < 0)
return log_error(r, "sd_bus_add_object_vtable()");
/* يُسند للخدمة اسم عابر مبدئيًا. أضف أيضًا اسمًا
* معروفًا، ليعرف العملاء من يستدعون. يجب أن يكون هذا
* غير متزامن، لأن D-Bus قد لا يكون متاحًا بعد. سيتحقق الاستدعاء الراجع
* مما إذا كان الخطأ متوقعًا أم لا، في حال فشله.
* https://www.freedesktop.org/software/systemd/man/sd_bus_request_name.html
*/
r = sd_bus_request_name_async(*o->bus,
NULL,
"org.freedesktop.ReconnectExample",
0,
request_name_callback,
o);
if (r < 0)
return log_error(r, "sd_bus_request_name_async()");
/* عند قطع اتصال D-Bus سيُستدعى هذا الاستدعاء الراجع، والذي سيُعد
* الاتصال مرة أخرى. يجب أن يكون هذا غير متزامن، لأن D-Bus قد لا
* يكون متاحًا بعد.
* https://www.freedesktop.org/software/systemd/man/sd_bus_match_signal_async.html
*/
r = sd_bus_match_signal_async(*o->bus,
NULL,
"org.freedesktop.DBus.Local",
NULL,
"org.freedesktop.DBus.Local",
"Disconnected",
on_disconnect,
NULL,
o);
if (r < 0)
return log_error(r, "sd_bus_match_signal_async()");
/* ألحق كائن الناقل بحلقة الأحداث لتُعالج الاستدعاءات والإشارات.
* https://www.freedesktop.org/software/systemd/man/sd_bus_attach_event.html
*/
r = sd_bus_attach_event(*o->bus, *o->event, 0);
if (r < 0)
return log_error(r, "sd_bus_attach_event()");
return 0; } int main(int argc, char **argv) {
/* يجب التخلي عن الناقل قبل انتهاء البرنامج. تسمح لنا
* سمة التنظيف بالقيام بذلك بشكل جميل ونظيف كلما خرجنا من الكتلة.
*/
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
object o = {
.example = "example",
.bus = &bus,
.event = &event,
};
int r;
/* أنشئ بنية بيانات لحلقة الأحداث، بمعاملات مبدئية.
* https://www.freedesktop.org/software/systemd/man/sd_event_default.html
*/
r = sd_event_default(&event);
if (r < 0)
return log_error(r, "sd_event_default()");
/* ستنتهي حلقة الأحداث مبدئيًا عند اختفاء جميع المصادر،
* لذا يجب علينا إبقاؤها 'مشغولة'. سجّل معالجة الإشارات للقيام بذلك.
* https://www.freedesktop.org/software/systemd/man/sd_event_add_signal.html
*/
r = sd_event_add_signal(event, NULL, SIGINT|SD_EVENT_SIGNAL_PROCMASK, NULL, NULL);
if (r < 0)
return log_error(r, "sd_event_add_signal(SIGINT)");
r = sd_event_add_signal(event, NULL, SIGTERM|SD_EVENT_SIGNAL_PROCMASK, NULL, NULL);
if (r < 0)
return log_error(r, "sd_event_add_signal(SIGTERM)");
r = setup(&o);
if (r < 0)
return EXIT_FAILURE;
/* ادخل الحلقة الرئيسة، ولن تخرج إلا عند sigint/sigterm.
* https://www.freedesktop.org/software/systemd/man/sd_event_loop.html
*/
r = sd_event_loop(event);
if (r < 0)
return log_error(r, "sd_event_loop()");
/* https://www.freedesktop.org/software/systemd/man/sd_bus_release_name.html */
r = sd_bus_release_name(bus, "org.freedesktop.ReconnectExample");
if (r < 0)
return log_error(r, "sd_bus_release_name()");
return 0; }
على الرغم من أن تمرير الموارد من دورة إعادة تشغيل ناعمة إلى التالية ممكن بهذه الطريقة، إلا أننا نقترح بشدة استخدام هذه الوظيفة باعتدال فقط، لأنها تخلق نظامًا أكثر هشاشة حيث قد تُخلط الموارد من إصدارات مختلفة من نظام التشغيل والتطبيقات مع عواقب غير متوقعة. يوصى بشكل خاص بـ تجنب السماح للعمليات بالبقاء حية بعد عملية إعادة التشغيل الناعمة، لأن هذا يعني أن تحديثات الكود ستكون بالضرورة غير مكتملة، وعادة ما تُثبّت العمليات موارد أخرى متنوعة (مثل نظام ملفات الذي تستند إليه)، مما يزيد من استهلاك الذاكرة (حيث قد يَبقى إصداران من نظام التشغيل/التطبيق/نظام الملفات في الذاكرة). يتطلب ترك العمليات قيد التشغيل أثناء عملية إعادة التشغيل الناعمة فصل الخدمة بشكل شامل عن بقية نظام التشغيل، أي تقليل IPC وتقليل مشاركة الموارد مع بقية نظام التشغيل. الآلية الممكنة لتحقيق ذلك هي مفهوم الخدمات المحمولة[1]، ولكن تأكد من عدم تثبيت أي مورد من أنظمة ملفات نظام تشغيل المضيف عبر BindPaths= أو إعدادات وحدة مماثلة، وإلا سيبقى نظام الملفات القديم الأصلي موصولاً طالما أن الوحدة قيد التشغيل.
ملاحظات¶
لاحظ أنه نظرًا لعدم تنفيذ systemd-shutdown(8)، فلن تُنفذ الملفات التنفيذية في /usr/lib/systemd/system-shutdown/ أيضًا.
لاحظ أنه يجب عدم تنفيذ systemd-soft-reboot.service (والوحدات ذات الصلة) مباشرة أبدًا. بدلاً من ذلك، استحث إغلاق النظام بأمر مثل systemctl soft-reboot.
لاحظ أنه إذا ضُبط نظام ملفات جذر جديد على "/run/nextroot/"، فستُجرى إعادة تشغيل ناعمة (soft-reboot) عند استدعاء الأمر reboot.
انظر أيضًا¶
systemd(1)، systemctl(1)، systemd.special(7)، systemd-poweroff.service(8)، systemd-suspend.service(8)، bootup(7)
ملاحظات¶
- 1.
- الخدمات المحمولة
ترجمة¶
تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي <zayed.alsaidi@gmail.com>
هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.
إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: kde-l10n-ar@kde.org.
| systemd 261~rc3 |