SYSTEMD-SOFT-REBOOT.SERVICE(8) systemd-soft-reboot.service systemd-soft-reboot.service - systemd-soft-reboot.service systemd-soft-reboot.service soft-reboot.target . SIGTERM ( ) SIGKILL. /run/nextroot/ ( ) . ( ) . : o systemd-shutdown(8). o initrd. o . o . o . o . o initrd. : o . o ( /proc/sys/ "sysctl" /sys/) . /etc/sysctl.d/ . . : o . DefaultDependencies=no ( Conflicts=shutdown.target ) . FileDescriptorStorePreserve= . systemd.service(5) . o .socket ( ) . ( DefaultDependencies=no.) o /run/ . o ( DefaultDependencies=no). SIGTERM SIGKILL SurviveFinalKillSignal=yes IgnoreOnIsolate=yes. . basic.target . . : [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 o . foo@test.service system-foo.slice : [Unit] SurviveFinalKillSignal=yes IgnoreOnIsolate=yes DefaultDependencies=no o . ( DefaultDependencies=no Conflicts=umount.target) o D-Bus D-Bus . sd-bus(3) . /* 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': * * To get the property via busctl: * * $ busctl --user get-property org.freedesktop.ReconnectExample \ * /org/freedesktop/ReconnectExample \ * org.freedesktop.ReconnectExample \ * Example * s "example" */ #include #include #include #include #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. https://systemd.io/PORTABLE_SERVICES 3 . . : . systemd 260.2 SYSTEMD-SOFT-REBOOT.SERVICE(8)