Vermeiden Sie das Kill des Systemd-Benutzerbereichs beim Herunterfahren

Vermeiden Sie das Kill des Systemd-Benutzerbereichs beim Herunterfahren

Ich erstelle eine Debian-Bookworm-Maschine, die als LXC-Container-Manager dient. Ich verwende nicht privilegierte LXC-Container, die mit dem Befehl lxc-unpriv-start gestartet werden, der einen systemd-Benutzerbereich erstellt. Ich erstelle einen Dienst, der meine Container beim Serverstart startet und beim Dienststopp ein sauberes Herunterfahren durchführt. Das Herunterfahren jedes Containers kann 2 oder 3 Minuten dauern. Wenn ich den Hauptdienst manuell stoppe, funktioniert alles gut. Das Problem tritt auf, wenn ich den Server herunterfahre, weil mein Dienst korrekt auf die Beendigung der Container wartet, aber in der Zwischenzeit beendet systemd-logind alle Benutzersitzungen und beendet damit auch meinen Container brutal.

Ich simuliere die Situation, indem ich eine Sleep-Only-Shell erstelle und sie ausführe mit

/usr/bin/systemd-run --user --scope -p "Delegate=yes" wait.sh &

und es wird beim Herunterfahren beendet. Wie kann ich das verhindern?

Antwort1

Linger sollte dieses Problem lösen.

Aushttps://www.freedesktop.org/software/systemd/man/loginctl.html

Aktivieren/deaktivieren Sie das Verweilen von Benutzern für einen oder mehrere Benutzer. Wenn dies für einen bestimmten Benutzer aktiviert ist, wird beim Systemstart ein Benutzermanager für den Benutzer erstellt und nach dem Abmelden beibehalten. Dadurch können nicht angemeldete Benutzer lang laufende Dienste ausführen. Nimmt einen oder mehrere Benutzernamen oder numerische UIDs als Argument. Wenn kein Argument angegeben ist, wird das Verweilen für den Benutzer der Sitzung des Anrufers aktiviert/deaktiviert.

loginctl enable-linger <username>

Wenn Sie „Linger“ für die Benutzersitzung aktivieren, können Ihre Container auch nach Ihrer Abmeldung oder während des Herunterfahrens des Systems weiter ausgeführt werden. Dies sollte verhindern, dass systemd-logind die Benutzersitzung und die zugehörigen Container zwangsweise beendet, und ihnen die Möglichkeit geben, ordnungsgemäß herunterzufahren.

Antwort2

Vorausgesetzt, der Containerstoppbefehl „blockiert“ (d. h. beendet sich, nachdem der Container gestoppt wurde), können Sie den Containerstartbefehl wahrscheinlich mit einem systemd-Benutzerdienst ausführen, anstatt direkt von einer Shell aus. Angenommen, Sie müssen mehrere Container starten, können Sie eine Dienstvorlage in schreiben $HOME/.config/systemd/user/. Der Dateiname einer Dienstvorlage sollte @vor .service(z. B. [email protected]) stehen.

Hier ist ein Beispiel für Sie:

[Unit]
PartOf=%i.scope
After=%i.scope

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/systemd-run --user --scope -u %i sh -c 'sleep 1d &'
ExecStop=/usr/bin/sleep 1m

Wie Sie sehen, muss der Bereichsname „bekannt“ sein und darf nicht generiert werden.

Mit der Vorlage können Sie den Container jetzt z. B. mit starten systemctl --user start test@container-a. Sie sollten jetzt sehen, dass der entsprechende Bereich bestehen bleibt, bis sein „Agent“-Dienst gestoppt wurde (d. h. der ExecStop=Befehl beendet wurde).

Sie müssen es möglicherweise immer dann ausführen, systemctl --user daemon-reloadwenn Sie Änderungen an den Servicedateien (Vorlagendateien) vorgenommen haben.

PS: Wenn Sie dem Befehl zum Starten/Stoppen des Containers zusätzliche containerspezifische Argumente übergeben müssen (die nicht dieselbe Zeichenfolge wie der Bereichsname sind), müssen Sie wahrscheinlich mehrere Servicedateien schreiben, anstatt eine Vorlage zu verwenden.

verwandte Informationen