SYSTEMD-SOFT-REBOOT.SERVICE(8) systemd-soft-reboot.service
BEZEICHNUNG
systemd-soft-reboot.service - Neustartaktion im Anwendungsraum
UBERSICHT
systemd-soft-reboot.service
BESCHREIBUNG
systemd-soft-reboot.service ist ein Systemdienst, der von
soft-reboot.target hereingezogen wird und fur die Durchfuhrung einer
Neustartaktion rein im Anwendungsraum verantwortlich ist. Beim Aufruf
wird er ein Signal SIGTERM an alle noch laufenden Prozesse senden (aber
wartet nicht darauf, dass sich die Prozesse beenden) und folgt dann mit
SIGKILL. Falls das Verzeichnis /run/nextroot/ existiert (dies kann ein
normales Verzeichnis, ein Verzeichnis-Einhangepunkt oder ein Symlink
auf diese sein), dann wird es die Dateisystemwurzel dorthin umschalten.
Es fuhrt dann den Diensteverwalter von dem (jetzt moglicherweise neuen)
Wurzeldateisystem erneut aus, wodurch eine neue Systemstarttransaktion
in die Warteschlange kommt, wie bei einem normalen Systemneustart.
Solch eine reine Neustartaktion im Anwendungsraum erlaubt das
Aktualisieren oder Zurucksetzen der Gesamtheit des Anwendungsraums mit
minimaler Ausfallzeit, da die Neustartaktion nicht folgende Punkte
durchlaufen muss:
o Die zweite Phase des regularen Herunterfahrens, wie von
systemd-shutdown(8) implementiert.
o Die dritte Phase des regularen Herunterfahrens, d.h. der Ruckkehr
in den Initrd-Kontext.
o Die Hardware-Neustart-Aktion.
o Die Firmware-Initialisierung.
o Die Initialisierung des Systemstartprogramms.
o Die Kernel-Initialisierung.
o Die Initrd-Initialisierung.
Allerdings hat diese Art des Neustarts auch Nachteile:
o Die Betriebssystemaktualisierung bliebt unvollstandig, da der
Kernel nicht zuruckgesetzt wird und weiter lauft.
o Kerneleinstellungen (wie die Einstellungen in /proc/sys/, bekannt
auch als >>sysctl<<- oder /sys/-Einstellungen) werden nicht
zuruckgesetzt.
Diese Beschrankungen konnen mit verschiedenen Mitteln adressiert
werden, die ausserhalb des Umfangs dieser Dokumentation sind, wie
beispielsweise dem Live-Patchen des Kernels und hinreichend
umfangreichen Dateien in /etc/sysctl.d/.
RESSOURCEN-WEITERGABE
Verschiedene Laufzeit-Betriebssystem-Ressourcen konnen von einer
Systemlaufzeit zu der nachsten uber die Neustartaktion im
Anwendungsraum hinweg weitergegeben werden. Konkret:
o Dateideskriptoren, die im Dateideskriptorspeicher von Diensten
abgelegt sind, die bis zum allerletzten Ende aktiv bleiben, werden
zum nachsten Start weitergegeben, wo sie in dem
Dateideskriptorspeicher der gleichen Unit abgelegt werden. Damit
dies funktioniert, mussen Units DefaultDependencies=no deklarieren
(und ein manuelles Conflicts=shutdown.target und ahnliches
vermeiden), um sicherzustellen, dass sie nicht normal wahrend der
Herunterfahraktion des Systems beendet werden. Alternativ konnen
Sie FileDescriptorStorePreserve= verwenden, um dem
Dateideskriptorspeicher zu erlauben, festgehalten zu werden, selbst
wenn die Unit heruntergefahren ist. Siehe systemd.service(5) zu
Details des Dateideskriptorspeichers.
o Entsprechend bleiben Dateideskriptoren offen (auch verbindbar),
die .socket-Units zugeordnet sind, falls die Units nicht wahrend
des Ubergangs gestoppt werden. (Dies wird durch
DefaultDependencies=no erreicht.)
o Das Dateisystem /run/ bleibt eingehangt und gefullt und kann zur
Ubergabe von Zustandsinformationen zwischen Neustartzyklen im
Anwendungsraum verwandt werden.
o Diensteprozesse konnen uber den Ubergang hinweg, hinter den
weichen Neustart und in die nachste Sitzung hinein laufen, falls
sie in Diensten abgelegt sind, die bis zum allerletzten Ende des
Herunterfahrens aktiv bleiben (was wiederum durch
DefaultDependencies=no erreicht wird). Sie mussen auch so
eingerichtet werden, dass sie das Beenden mit den vorher erwahnten
SIGTERM und SIGKILL mittels SurviveFinalKillSignal=yes vermeiden
und auch so konfiguriert sein, dass sie das Stoppen beim Isolieren
mittels IgnoreOnIsolate=yes vermeiden. Sie mussen auch so
konfiguriert sein, dass sie beim normalen Herunterfahren,
Neustarten oder im Wartungsmodus angehalten werden. Schliesslich
mussen sie nach basic.target angeordnet sein, um die korrekte
Sortierung beim Systemstart sicherzustellen. Falls irgendwelche
neuen oder angepassten Units zum Hineinisolieren verwandt werden
oder diese eine aquivalente Herunterfahrfunktionalitat
bereitstellen, dann mussen diese Prozesse auch manuell fur die
korrekte Sortierung und Konflikte konfiguriert sein. Beispiel:
[Unit]
Description=Mein uberlebender Dienst
SurviveFinalKillSignal=yes
IgnoreOnIsolate=yes
DefaultDependencies=no
After=basic.target
Conflicts=reboot.target
Before=reboot.target
Conflicts=kexec.target
Before=kexec.target
Conflicts=poweroff.target
Before=poweroff.target
Conflicts=halt.target
Before=halt.target
Conflicts=rescue.target
Before=rescue.target
Conflicts=emergency.target
Before=emergency.target
[Service]
Type=oneshot
ExecStart=sleep infinity
o Dateisystemeinhangungen konnen wahrend des Ubergangs eingehangt
bleiben und komplexe Speichersysteme angehangt, falls sie so
konfiguriert wurden, dass sie bis zum allerletzten Ende des
Herunterfahrprozesses aktiv bleiben. (Dies wird auch mittels
DefaultDependencies=no und dem Vermeiden von
Conflicts=umount.target erreicht.)
o Falls die Unit einen Dienst uber D-Bus veroffentlicht, muss die
Verbindung nach einem weichen Neustart neu etabliert werden, da der
D-Bus-Vermittler gestoppt und dann wieder gestartet wird. Unter
Verwendung der Bibliothek sd-bus(3) kann dies durch Anpassung des
folgenden Beispiels erfolgen.
/* SPDX-License-Identifier: MIT-0 */
/* Implementiert einen D-Bus-Dienst, der sich automatisch neu verbindet, wenn der Systembus neu gestartet wird.
*
* Kompilieren Sie mit >>cc sd_bus_service_reconnect.c $(pkg-config --libs --cflags libsystemd)<<
*
* Um dem Programm zu erlauben, die Eigentumerschaft des Namen >>org.freedesktop.ReconnectExample<< anzunehmen,
* fugen Sie folgendes als /etc/dbus-1/system.d/org.freedesktop.ReconnectExample.conf hinzu
* und laden Sie den Verwalter mit >>systemctl reload dbus<< neu:
*
* Um die Eigenschaften mittel busctl zu erlangen:
*
* $ 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)))
#define check(x) ({ \
int _r = (x); \
errno = _r < 0 ? -_r : 0; \
printf(#x ": %m\n"); \
if (_r < 0) \
return EXIT_FAILURE; \
})
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,
"Unbekannte Eigenschaft >>%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) {
check(setup((object *)userdata));
return 0;
}
/* Sicherstellen, dass sich die Ereignisschleife mit einem klaren Fehler beendet, falls das Erlangen des gut bekannten Dienstenamens fehlschlagt */
static int request_name_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
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; /* Der Bus ist nicht verfugbar, spater erneut versuchen */
printf("Fehlschlag beim Anfragen des Namens: %s\n", error->message);
object *o = userdata;
check(sd_event_exit(*o->event, -sd_bus_error_get_errno(error)));
return 1;
}
static int setup(object *o) {
/* Falls es eine Neuverbindung ist, muss das Busobjekt geschlossen, abgehangt von
* der Ereignisschleife und neu erstellt werden.
* 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) {
check(sd_bus_detach_event(*o->bus));
*o->bus = sd_bus_close_unref(*o->bus);
}
/* Einrichten eines neuen Busobjekts fur den Systembus, dessen Konfiguration, auf die Verfugbarkeit
* des D-Busses zu warten, statt bei Nichtverfugbarkeit fehlzuschlagen und ihn zu starten. Alle
* folgenden Aktionen sind asyncron und blockieren nicht beim Warten auf die Verfugbarkeit des 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
*/
check(sd_bus_new(o->bus));
check(sd_bus_set_address(*o->bus, "unix:path=/run/dbus/system_bus_socket"));
check(sd_bus_set_bus_client(*o->bus, 1));
check(sd_bus_negotiate_creds(*o->bus, 1, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS));
check(sd_bus_set_watch_bind(*o->bus, 1));
check(sd_bus_start(*o->bus));
/* Veroffentlicht eine Schnittstelle auf dem Bus unter Angabe des gut bekannte Objektzugriffspfades
und des offentlichen Schnittstellennamens.
* https://www.freedesktop.org/software/systemd/man/sd_bus_add_object.html
* https://dbus.freedesktop.org/doc/dbus-tutorial.html
*/
check(sd_bus_add_object_vtable(*o->bus,
NULL,
"/org/freedesktop/ReconnectExample",
"org.freedesktop.ReconnectExample",
vtable,
o));
/* Standardmassig ist dem Dienst nur ein fluchtiger Name zugewiesen. Der gut bekannte
* wird hinzugefugt, damit Clients ihn fur den Aufruf kennen. Dies muss asynchron erfolgen
* da der D-Bus noch nicht verfugbar sein konnte. Der Ruckruf wird prufen, ob der Fehler
* erwartet wurde oder nicht, falls er fehlschlagt.
* https://www.freedesktop.org/software/systemd/man/sd_bus_request_name.html
*/
check(sd_bus_request_name_async(*o->bus,
NULL,
"org.freedesktop.ReconnectExample",
0,
request_name_callback,
o));
/* Wenn der D-Bus abgetrennt wird, wird dieser Ruckruf aufgerufen, der die Verbindung
* erneut einrichtet. Dies muss asynchron erfolgen, da der D-Bus noch nicht verfugbar
* sein konnte.
* https://www.freedesktop.org/software/systemd/man/sd_bus_match_signal_async.html
*/
check(sd_bus_match_signal_async(*o->bus,
NULL,
"org.freedesktop.DBus.Local",
NULL,
"org.freedesktop.DBus.Local",
"Disconnected",
on_disconnect,
NULL,
o));
/* Das Bus-Objekt an die Ereignisschleife anhangen, so dass Aufrufe und Signale verarbeitet
* werden.
* https://www.freedesktop.org/software/systemd/man/sd_bus_attach_event.html
*/
check(sd_bus_attach_event(*o->bus, *o->event, 0));
return 0;
}
int main(int argc, char **argv) {
/* Der Bus sollte aufgegeben werden, bevor sich das Programm beendet. Die
* Aufraumattribute ermoglichen es, dass dies beim Verlassen des Blocks nett
* und sauber erfolgt.
*/
_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,
};
/* Erzeugt eine Ereignisschleifen-Datenstruktur mit Standard-Parametern.
* https://www.freedesktop.org/software/systemd/man/sd_event_default.html
*/
check(sd_event_default(&event));
/* Standardmassig wird sich die Ereignisschleife beenden, wenn alle Quellen verschwunden
* sind, daher muss sie >>belegt<< bleiben. Dafur wird Signalverarbeitung registriert.
* https://www.freedesktop.org/software/systemd/man/sd_event_add_signal.html
*/
check(sd_event_add_signal(event, NULL, SIGINT|SD_EVENT_SIGNAL_PROCMASK, NULL, NULL));
check(sd_event_add_signal(event, NULL, SIGTERM|SD_EVENT_SIGNAL_PROCMASK, NULL, NULL));
check(setup(&o));
/* Eintreten in die Hauptschleife, sie wird nur bei Sigint/Sigterm verlassen.
* https://www.freedesktop.org/software/systemd/man/sd_event_loop.html
*/
check(sd_event_loop(event));
/* https://www.freedesktop.org/software/systemd/man/sd_bus_release_name.html */
check(sd_bus_release_name(bus, "org.freedesktop.ReconnectExample"));
return 0;
}
Obwohl die Weitergabe von Ressourcen von einem weichen Neustartzyklus
zum nachsten auf diese Art moglich ist, empfehlen wir nachdrucklich,
diese Funktionalitat nur restriktiv zu verwenden, da sie zu fragileren
Systemen fuhrt, da Ressourcen von verschiedenen Versionen des
Betriebssystems und Anwendungen mit unvorhergesehenen Konsequenzen
gemischt werden. Insbesondere wird empfohlen zu vermeiden, es Prozessen
zu erlauben, die weiche Neustartaktion zu uberleben, da dies bedeutet,
dass Code-Aktualisierungen notwendigerweise unvollstandig sind und
Prozesse typischerweise verschiedene andere Ressourcen festhalten (wie
das ihnen zugrundeliegende Dateisystem), wodurch der Speicherverbrauch
erhoht wird (da zwei Versionen des Betriebssystems/der Anwendung/des
Dateisystems im Speicher verbleiben konnen). Das Weiterlaufen von
Prozessen wahrend einer weichen Neustartaktion benotigt die umfassende
Abtrennung des Dienstes vom Betriebssystem, d.h. die Minimierung von
IPC und die Reduktion der gemeinsamen Verwendung von Ressourcen mit dem
Rest des Betriebssystems. Ein moglicher Mechanismus, dies zu erreichen,
ist das Konzept des Portablen Dienstes[1]. Stellen Sie aber sicher,
dass keine Ressource vom Betriebssystem-Dateisystem des Hauptsystems
mittels BindPaths= oder ahnlichen Unit-Einstellungen festgehalten wird.
Andernfalls verbleibt das alte, ursprungliche Dateisystem eingehangt,
solange die Unit lauft.
ANMERKUNGEN
Beachten Sie, dass auch die Programme in
/usr/lib/systemd/system-shutdown/ nicht ausgefuhrt werden, da
systemd-shutdown(8) nicht ausgefuhrt wird.
Beachten Sie, dass systemd-soft-reboot.service (und zugehorige Units)
niemals direkt ausgefuhrt werden sollten. Losen Sie stattdessen das
Herunterfahren des Systems mit Befehlen wie >>systemctl soft-reboot<<
aus.
Falls ein neues Wurzeldateisystem unter >>/run/nextroot/<< eingerichtet
wurde, beachten Sie, dass ein soft-reboot durchgefuhrt wird, wenn der
Befehl reboot aufgerufen wird.
SIEHE AUCH
systemd(1), systemctl(1), systemd.special(7),
systemd-poweroff.service(8), systemd-suspend.service(8), bootup(7)
ANMERKUNGEN
1. Portable Dienste
https://systemd.io/PORTABLE_SERVICES
UBERSETZUNG
Die deutsche Ubersetzung dieser Handbuchseite wurde von Helge
Kreutzmann erstellt.
Diese Ubersetzung ist Freie Dokumentation; lesen Sie die GNU General
Public License Version 3
oder neuer bezuglich der Copyright-Bedingungen. Es wird KEINE HAFTUNG
ubernommen.
Wenn Sie Fehler in der Ubersetzung dieser Handbuchseite finden,
schicken Sie bitte eine E-Mail an die Mailingliste der Ubersetzer
.
systemd 255 SYSTEMD-SOFT-REBOOT.SERVICE(8)