Ich habe ein Dotnet-Programm, das innerhalb von Bash in tmux läuft und gelegentlich mit einem Fehlercode ungleich Null fehlschlägt. Ich versuche, eine systemd-Dienstdatei zu verwenden, um mein Dotnet-Programm innerhalb von tmux programmgesteuert zu starten.
Hier ist die Servicedatei:
[Unit]
Description=dotnet application
[Service]
Type=forking
ExecStart=/home/alpine_sour/scripts/rofdl
Restart=always
User=root
[Install]
WantedBy=multi-user.target
Hier ist das Rofdl-Shell-Skript:
#!/bin/bash
/usr/bin/tmux kill-session -t "rof" 2> /dev/null || true
/usr/bin/tmux new -s "rof" -d "cd /home/alpine_sour/rofdl && dotnet run"
Wenn ich den Dienst jetzt starte, wählt systemd die Haupt-PID als tmux-Server, was vermutlich daran liegt, dass es der erste ausgeführte Befehl war. Wenn also mein Programm im tmux-Fenster mit IRGENDEINEM Fehlercode beendet wird UND keine weiteren Fenster vorhanden sind, wird der tmux-Server mit einem Erfolgsfehlercode beendet, was dazu führt, dass systemd nicht neu gestartet wird. Selbst wenn ich Restart=always festlegen würde, würde der tmux-Server nur neu gestartet, wenn mein Programm fehlschlägt UND keine weiteren Fenster vorhanden sind.
Process: 24980 ExecStart=/home/alpine_sour/scripts/rofdl (code=exited, status=0/SUCCESS)
Main PID: 24984 (tmux: server)
├─24984 /usr/bin/tmux new -s rofdl -d cd /home/alpine_sour/rofdl && dotnet run -- start
├─24985 sh -c cd /home/alpine_sour/rofdl && dotnet run -- start
├─24987 dotnet run -- start
└─25026 dotnet exec /home/alpine_sour/rofdl/bin/Debug/netcoreapp2.1/rofdl.dll start
Ich frage mich also, wie ich systemd dazu bringen kann, die niedrigste Ebene des Prozesszweigs zu verfolgen und nicht den Tmux-Server auf höherer Ebene. Ich muss systemd irgendwie anweisen, den untergeordneten Prozess des Tmux-Servers zu verfolgen und nicht den Server selbst, und entsprechend neu zu starten.
Antwort1
Vorbemerkungen
- Diese Antwort basiert auf Experimenten in Debian 9.
- Ich gehe davon aus, dass Ihr Dienst ein Systemdienst (in
/etc/systemd/system
) ist. - Was Sie am Ende des Fragentextes gepostet haben, sieht aus wie einAuszugvon
systemctl status …
. Es steht nichts über cgroups. Diese Antwort setzt vorausKontrollgruppensind beteiligt. Ich denkesystemd
, sie sind erforderlich, also müssen sie es sein. Der Befehl selbst kann in einer Schleife ausgeführt werden, bis er erfolgreich ist:
cd /home/alpine_sour/rofdl && while ! dotnet run; do :; done
aber ich verstehe, dass Sie eine
systemd
Lösung wollen.
Probleme
Bitte lesen Sie zuerstWie tmux
funktioniert. Es ist sehr hilfreich zu verstehen, welcher Prozess wessen Kind ist.
Welche Prozesse gehören zum Service
In Ihrem ursprünglichen Fall wird der Dienst als inaktiv betrachtet (und ggf. zum Neustart bereit), nachdem alle Prozesse aus seiner Kontrollgruppe beendet wurden.
tmux
Ihr Skript versucht, die alte Sitzung zu beenden , nicht den alten tmux
Server. Dann startet tmux new
(entspricht tmux new-session
) entweder ein neuer Server oder verwendet den alten.
Wenn das alte verwendet wird,
dotnet …
sind weder der Server noch Ihr Befehl () ein Nachkomme des Skripts. Diese Prozesse gehören nicht zur mit dem Dienst verknüpften Kontrollgruppe. Nachdem das Skript beendet wurde,systemd
wird der Dienst als inaktiv betrachtet.Wenn ein neuer Server gestartet wird,
tmux
werden der Server und der Befehl der mit dem Dienst verknüpften Kontrollgruppe zugewiesen. Dann kann unser Befehl beendet werden, aber wenn sich auf dem Server andere Sitzungen/Fenster (die später erstellt werden) befinden, kann der Server bestehen bleiben undsystemd
den Dienst als aktiv betrachten.
Wenn es einen Hauptprozess gibt, wird die gesamte Kontrollgruppe beendet, nachdem der Hauptprozess beendet wurde. Bei Type=simple
ist der Hauptprozess derjenige, der durch angegeben wird ExecStart=
. Bei Type=forking
müssen Sie PIDFile=
eine PID verwenden und auf diese Weise übergeben, um den Hauptprozess anzugeben. Und wenn Sie einen Dienst beenden, systemd
werden alle Prozesse beendet, die zu dem Dienst gehören. Daher ist es wichtig, nur Prozesse in die Kontrollgruppe aufzunehmen, die für den Dienst spezifisch sind. In Ihrem Fall möchten Sie möglicherweise tmux
den Server ausschließen, auch wenn er innerhalb des Dienstes gestartet wird.
Es gibt Tools/Möglichkeiten, Prozesse zwischen Kontrollgruppen zu verschieben. Oder Sie können einen separaten tmux
Server speziell für den Dienst ausführen.
Wer systemd
weiß, welcher Exit-Status zu verwenden ist
Restart=on-failure
legt die Abhängigkeit vom Beendigungsstatus des Hauptprozesses fest. Es Type=forking
wird empfohlen, es zu verwenden, PIDFile=
damit systemd
Sie wissen, welcher Beendigungsstatus verwendet werden soll.
systemd
Der Beendigungsstatus kann jedoch möglicherweise abgerufen werden, möglicherweise aber auch nicht.
Wer ruft den Exit-Status ab?
Nach dem Beenden eines untergeordneten Elements kann das übergeordnete Element den Beendigungsstatus abrufen (vgl.Zombie-Prozess).
Unabhängig davon, ob der tmux
Server alt oder neu ist, wird Ihr Befehl kein Kind von sein, systemd
es sei denn, er wird verwaist. Der Kernel setzt seinen Elternteil auf PID 1 (oder ein anderes) und der neue Elternteil ist der rechte systemd
.
Der von Ihnen angegebene Befehl tmux new
veranlasst den tmux
Server, eine Shell auszuführen. Anschließend wird die Shell entweder ausgeführt dotnet
und wartet auf ihre Beendigung oder exec
führt eine Shell-Operation aus, dotnet
wobei der tmux
Server als übergeordneter Server beibehalten wird. In jedem Fall dotnet
hat er einen übergeordneten Server, der nicht systemd
.
Sie könnten es dotnet
wie folgt verwaist machen: nohup dotnet … &
und dann die besagte Shell beenden lassen. Sie müssten auch die PID speichern und PIDFile=
in der Unit-Konfigurationsdatei verwenden, damit der Dienst weiß, welchen Prozess er überwachen soll. Dann könnte es irgendwie funktionieren.
Um es klar zu sagen: In meinen Tests nohup sleep 300 &
wurde es erfolgreich übernommen, und systemd
wer konnte dann seinen Beendigungsstatus abrufen (nachdem ich mich um die Cgroups gekümmert hatte).
tmux
Aber da Sie in erster Linie verwenden möchten , gehe ich davon aus, dass Ihr Befehl mit dem Terminal interagiert. Alsonohup
ist hier nicht das richtige Werkzeug. Einen Prozess zu verwaisten, während er mit dem Terminal verbunden bleibt, kann schwierig sein. Sie möchten ihn verwaist machen, können die Shell darin aber nicht tmux
einfach beenden, da dies ihre Fensterfläche zerstören würde (oder sie in einem toten Zustand belassen würde).
Hinweis : Type=forking
Es basiert auf der Übernahme durch systemd
. Der Hauptdienstprozess soll sich verzweigen und beenden. Dann systemd
übernimmt er sein Kind. Ein solcher Daemon sollte jedoch nicht mit einem Terminal interagieren.
Ein anderer Ansatz besteht darin, die Shell innerhalb des tmux
Servers exec
ausführen zu lassen dotnet
. Nach dem Beenden tmux
kennt der Server (als übergeordneter Server) seinen Beendigungsstatus. Unter bestimmten Umständen können wir den Server von einem anderen Skript aus abfragen und den Beendigungsstatus abrufen.
Oder die ausgelöste Shell tmux new
speichert den Status in einer Datei, sodass er von einem anderen Skript abgerufen werden kann.
Da das, was Sie ausführen, mit Sicherheit ExecStart=
ein Kind von ist systemd
, ist dies der beste Kandidat für „ein anderes Skript“. Es sollte warten, bis es den Beendigungsstatus abrufen kann, und ihn dann als seinen eigenen Beendigungsstatus verwenden, damit er ihn erhält. Beachten Sie, dass der Dienst in diesem Fall systemd
sein sollte .Type=simple
Alternativ können Sie auch dotnet …
außerhalb von beginnen tmux
und dannreptyr
von innerhalb des tmux
Servers. Auf diese Weise kann von Anfang an dotnet
ein Kind von sein , es können jedoch Probleme auftreten, wenn Sie versuchen, dessen TTY zu stehlen.systemd
Lösungen und Beispiele
reptyr
Zutmux
Dieses Beispiel führt das Skript in aus tty2
. Das Skript bereitet sich vor tmux
und exec
sendet an . Schließlich versucht dotnet
eine Shell darin, tty von dem zu stehlen, was jetzt ist .tmux
dotnet
Die Servicedatei:
[Unit]
Description=dotnet application
[email protected]
[Service]
Type=simple
ExecStart=/home/alpine_sour/scripts/rofdl
Restart=on-failure
User=root
StandardInput=tty
TTYPath=/dev/tty2
TTYReset=yes
TTYVHangup=yes
[Install]
WantedBy=multi-user.target
/home/alpine_sour/scripts/rofdl
:
#!/bin/sh
tmux="/usr/bin/tmux"
"$tmux" kill-session -t "rof" 2> /dev/null
"$tmux" new-session -s "rof" -d "sleep 5; exec /usr/bin/reptyr $$" || exit 1
cd /home/alpine_sour/rofdl && exec dotnet run
Anmerkungen:
- Meine Tests mit
htop
stattdessendotnet run
ergaben einen Race Condition (htop
ändert die Einstellungen des Terminals,reptyr
kann stören; dahersleep 5
kein guter Workaround) und Probleme mit der Mausunterstützung. - Es ist möglich, den Server aus der mit dem Dienst verknüpften Kontrollgruppe zu entfernen . Das möchten Sie wahrscheinlich tun. Sehen Sie weiter unten, wo im Code
tmux
das steht ./sys/fs/cgroup/systemd/
Ohne tmux
?
Die obige Lösung wird /dev/tty2
trotzdem verwendet. Wenn Sie tmux
nur ein Steuerterminal bereitstellen müssen, ziehen Sie cd /home/alpine_sour/rofdl && exec dotnet run
ohne reptyr
, ohne in Betracht tmux
. Auch ohne das Skript:
ExecStart=/bin/sh -c 'cd /home/alpine_sour/rofdl && exec dotnet run' rofdl
Das ist das Einfachste.
Separater tmux
Server
tmux
ermöglicht es Ihnen, mehr als einen Server pro Benutzer auszuführen. Sie müssen -L
oder -S
(siehe man 1 tmux
) einen Socket angeben und dann dabei bleiben. Auf diese Weise kann Ihr Dienst einen exklusiven tmux
Server ausführen. Vorteile:
- Der Server und alles, was Sie darin ausführen,
tmux
gehört standardmäßig zur Kontrollgruppe des Dienstes. - Der Dienst kann den Server zerstören,
tmux
ohne dass das Risiko besteht, dass irgendjemand (oder irgendetwas) anderes seine Sitzungen verliert. Niemand sonst sollte diesen Server verwenden, es sei denn, er möchte den Dienst überwachen/mit ihm interagieren. Wenn ihn jemand für etwas anderes verwendet, ist das sein Problem.
Die Möglichkeit, den Server beliebig zu beenden, tmux
ermöglicht es Ihnen, Prozesse, die in ausgeführt werden, zu verwaisten tmux
. Betrachten Sie das folgende Beispiel.
Die Servicedatei:
[Unit]
Description=dotnet application
[Service]
Type=forking
ExecStart=/home/alpine_sour/scripts/rofdl
Restart=on-failure
User=root
PIDFile=/var/run/rofdl.service.pid
[Install]
WantedBy=multi-user.target
/home/alpine_sour/scripts/rofdl
:
#!/bin/sh
tmux="/usr/bin/tmux"
service="rofdl.service"
"$tmux" -L "$service" kill-server 2> /dev/null
"$tmux" -L "$service" new-session -s "rof" -d '
trap "" HUP
ppid="$PPID"
echo "$$" > '" '/var/run/$service.pid' "'
cd /home/alpine_sour/rofdl && dotnet run
status="$?"
'" '$tmux' -L '$service' kill-server 2> /dev/null "'
while [ "$ppid" -eq "$(ps -o ppid= -p "$$")" ]; do sleep 2; done
exit "$status"
' || exit 1
Erläuterung:
Das Hauptskript beendet den exklusiven
tmux
Server (sofern vorhanden) und startet ihn neu. Nachdem der Server gestartet ist, wird das Skript beendet. Der Dienst bleibt bestehen, da in der Kontrollgruppe noch mindestens ein Prozess übrig ist, nämlich der besagte Server.Der Server startet eine Shell, um das „innere“ Skript zu verarbeiten. Das Skript beginnt nach
'
und-d
endet'
vor||
. Es ist vollständig in Anführungszeichen gesetzt, aber die Anführungszeichen ändern sich einige Male von einfachen in doppelte Anführungszeichen und zurück. Dies liegt daran, dass$tmux
und$service
von der Shell erweitert werden müssen, die das Hauptskript verarbeitet. Andere Variablen (z. B.$status
) dürfen erst in der „inneren“ Shell innerhalb erweitert werdentmux
. Die folgende Ressource kann hilfreich sein:Parametererweiterung (Variablenerweiterung) und Anführungszeichen in Anführungszeichen.Die Shell im Inneren
tmux
bereitet sich darauf vor, das Signal zu ignorierenHUP
.Die Shell registriert ihre PID in der vom Dienst erwarteten PID-Datei.
Dann wird es ausgeführt
dotnet
und speichert seinen Beendigungsstatus (streng genommen, wenncd
es fehlschlägt, ist es der Beendigungsstatus voncd
).Die Shell beendet den
tmux
Server. Wir könnten dieskill "$PPID"
auch mit tun (sieheDas), aber wenn jemand den Server beendet hätte und ein anderer Prozess dessen PID erhalten hätte, würden wir einen falschen Prozess beenden. Die Adressierungtmux
ist sicherer. Denn dadurchtrap
bleibt die Shell erhalten.Dann wiederholt die Shell die Schleife, bis ihre PPID eine andere ist als die vorherige. Wir können uns nicht auf den Vergleich
$ppid
mit verlassen$PPID
, da letzteres nicht dynamisch ist; wir rufen die aktuelle PPID von abps
.Jetzt weiß die Shell, dass sie einen neuen übergeordneten Status hat, es sollte sein
systemd
. Erst jetztsystemd
kann der Beendigungsstatus von der Shell abgerufen werden. Die Shell wird mit dem exakten Beendigungsstatus beendet, derdotnet
zuvor abgerufen wurde. Auf diese Weisesystemd
erhält man den Beendigungsstatus, obwohl erdotnet
nie ihr untergeordneter Status war.
Abrufen des Beendigungsstatus vom gemeinsamen tmux
Server
Ihr ursprünglicher Ansatz verwendet einen gemeinsamen (Standard-) tmux
Server und manipuliert nur eine Sitzung mit dem Namen rof
. Im Allgemeinen können andere Sitzungen vorhanden sein oder entstehen, daher sollte der Dienst niemals den gesamten Server beenden. Es gibt einige Aspekte. Wir sollten:
- Verhindern Sie
systemd
, dass dertmux
Server beendet wird, selbst wenn der Server innerhalb des Dienstes gestartet wurde. - Betrachten Sie
systemd
dendotnet
Prozess als Teil des Dienstes, auch wenn ertmux
nicht innerhalb des Dienstes gestartet wurde. - den Beendigungsstatus
dotnet
irgendwie abrufen.
Die Servicedatei:
[Unit]
Description=dotnet application
[Service]
Type=simple
ExecStart=/home/alpine_sour/scripts/rofdl
Restart=on-failure
User=root
[Install]
WantedBy=multi-user.target
Beachten Sie, dass dies Type=simple
jetzt der Fall ist, da das Hauptskript das einzige gesicherte untergeordnete Element ist, von dem wir den Beendigungsstatus abrufen können. Das Skript muss den Beendigungsstatus ermitteln dotnet …
und ihn als seinen eigenen melden.
/home/alpine_sour/scripts/rofdl
:
#!/bin/sh
tmux="/usr/bin/tmux"
service="rofdl.service"
slice="/sys/fs/cgroup/systemd/system.slice"
"$tmux" kill-session -t "rof" 2> /dev/null
( sh -c 'echo "$PPID"' > "$slice/tasks"
exec "$tmux" new-session -s "rof" -d "
'$tmux' set-option -t 'rof' remain-on-exit on "'
echo "$$" > '" '$slice/$service/tasks' "'
cd /home/alpine_sour/rofdl && dotnet run
exit "$?"
' || exit 1
)
pane="$("$tmux" display-message -p -t "rof" "#{pane_id}")"
while sleep 2; do
[ "$("$tmux" display-message -p -t "$pane" "#{pane_dead}")" -eq 0 ] || {
status="$("$tmux" display-message -p -t "$pane" "#{pane_dead_status}")"
status="${status:-255}"
exit "$status"
}
done
Erläuterung:
Wenn
tmux new-session
ein Server erstellt wird (weil es keinen gab), möchten wir ihn von Anfang an in einer anderen Kontrollgruppe haben, um einen Race Condition zu vermeiden, wenn etwas anderes den Server zu verwenden beginnt und wir seine Kontrollgruppe noch nicht geändert haben undsystemd
der Dienst aus irgendeinem Grund beendet werden soll. Ich habe versucht, estmux new-session
mit auszuführencgexec
, aber es ist fehlgeschlagen. Daher ein anderer Ansatz: eine Subshell, die ihre eigene Kontrollgruppe ändert (indem sie in schreibt/sys/fs/cgroup/systemd/system.slice/tasks
) und dannexec
in schreibttmux new-session
.Die darin enthaltene Shell
tmux
beginnt mit der Aktivierungremain-on-exit
der Option für die Sitzung. Nach der Beendigung bleibt der Bereich bestehen und ein anderer Prozess (in unserem Fall das Hauptskript) kann seinen Beendigungsstatus vomtmux
Server abrufen.In der Zwischenzeit ruft das Hauptskript die eindeutige ID des Bereichs ab, in dem die andere Shell ausgeführt wird. Wenn sich jemand an der Sitzung anmeldet oder neue Bereiche erstellt und mit ihnen spielt, kann das Hauptskript weiterhin den richtigen Bereich finden.
Die darin enthaltene Shell
tmux
registriert ihre PID in der mit dem Dienst verknüpften Kontrollgruppe, indem sie sie in schreibt/sys/fs/cgroup/systemd/system.slice/rofdl.service/tasks
.Die darin enthaltene Shell
tmux
führt ausdotnet …
. Nachdotnet
Beendigung wird die Shell beendet. Der von abgerufene Beendigungsstatusdotnet
wird von der Shell an dentmux
Server gemeldet.Aufgrund von
remain-on-exit on
bleibt die Scheibe nach dem Verlassen der „inneren“ Schale in einem toten Zustand.In der Zwischenzeit wird die Haupt-Shell in einer Schleife ausgeführt, bis der Bereich tot ist. Dann fragt sie den
tmux
Server nach dem entsprechenden Beendigungsstatus ab und meldet ihn als ihren eigenen. Auf diese Weisesystemd
erhält sie den Beendigungsstatus vondotnet
.
Anmerkungen:
Wieder gibt esAnführungszeichen in Anführungszeichen.
Anstelle von
dotnet run
könnte es seinexec dotnet run
. Die letzte Form ist nett:dotnet
ersetzt die innere Shell, sodass es einen Prozess statt zwei gibt. Das Problem ist, wenndotnet
durch ein Signal beendet wird, das es nicht verarbeiten kann. Es stellt sich heraus, dass#{pane_dead_status}
eine leere Zeichenfolge gemeldet wird, wenn der Prozess im Bereich durch ein Signal zwangsweise beendet wird. Die Aufrechterhaltung einer Shell zwischendotnet
undtmux
verhindert dies: Die Shell transformiert Informationen (siehediese Frage) und gibt eine Zahl zurück.Einige Shells (Implementierungen?) führen den allerletzten Befehl mit implicit aus
exec
, was wir nicht wollen. Deshalb habe ichexit "$?"
after verwendetdotnet …
.Wenn die Shell selbst jedoch zwangsweise beendet wird, tritt das Problem mit dem leeren Zustand
#{pane_dead_status}
erneut auf. Als letzte Möglichkeit wird derstatus="${status:-255}"
leere Zustand in255
(obwohl ich nicht sicher bin,255
ob dies in einem solchen Fall der beste Wert ist) umgewandelt.Es gibt einen Race Condition: Wenn das Hauptskript nach abfragt
tmux
,#{pane_id}
ist es möglicherweise nicht der richtige Bereich. Wenn jemand nachtmux new-session
und vor in der Sitzung eine Verbindung hergestellt und gespielt hattmux display-message
, erhalten wir möglicherweise einen falschen Bereich. Das Zeitfenster ist klein, aber trotzdem ist dies nicht so elegant, wie ich es wollte.Wenn Sie wie möglich auf der Konsole
tmux new-session
drucken könnten , sollte es kein Problem geben. Damit können Sie es innerhalb der Sitzung anzeigen. Es gibt keine Unterstützung für .#{pane_id}
tmux display-message -p
-PF
-p
Möglicherweise benötigen Sie eine Logik für den Fall, dass der
tmux
Server abgestürzt ist.
Abrufen des Beendigungsstatus über eine Datei
Das obige Beispiel kann geändert werden, ist also nicht remain-on-exit on
erforderlich #{pane_id}
(Race Condition vermieden, zumindest der beschriebene).
Die Servicedatei aus dem vorherigen Beispiel bleibt bestehen.
/home/alpine_sour/scripts/rofdl
:
#!/bin/sh
tmux="/usr/bin/tmux"
service="rofdl.service"
slice="/sys/fs/cgroup/systemd/system.slice"
statf="/var/run/$service.status"
rm "$statf" 2>/dev/null
"$tmux" kill-session -t "rof" 2> /dev/null
( sh -c 'echo "$PPID"' > "$slice/tasks"
exec "$tmux" new-session -s "rof" -d '
echo "$$" > '" '$slice/$service/tasks' "'
cd /home/alpine_sour/rofdl && dotnet run
echo "$?" > '" '$statf.tmp'
mv '$statf.tmp' '$statf'
" || exit 1
)
while sleep 2; do
status="$(cat "$statf" 2>/dev/null)" && exit "$status"
done
Der Mechanismus ist ziemlich unkompliziert: Die Hauptshell entfernt die alte Statusdatei (sofern vorhanden), löst sie aus tmux
und führt eine Schleife aus, bis die Datei wieder erscheint. Die „innere“ Shell schreibt den Beendigungsstatus in dotnet
die Datei, wenn sie bereit ist.
Anmerkungen:
- Was passiert, wenn die innere Shell beendet wird? Was passiert, wenn die Datei nicht erstellt werden kann? Es kann relativ leicht passieren, dass das Hauptskript die Schleife nicht verlassen kann.
- Es ist eine gute Praxis, in eine temporäre Datei zu schreiben und sie dann umzubenennen. Wenn wir das täten
echo "$?" > "$statf"
, würde die Datei leer erstellt und dann beschrieben. Dies könnte zu einer Situation führen, in der das Hauptskript eine leere Zeichenfolge als Status liest. Im Allgemeinen könnte der Empfänger unvollständige Daten erhalten: Lesen bis EOF, während der Sender mitten im Schreiben ist und die Datei noch wächst. Durch das Umbenennen wird sofort die richtige Datei mit dem richtigen Inhalt angezeigt.
Abschließende Anmerkungen
- Wenn Sie nicht darauf verzichten können
tmux
, erscheint die Lösung mit einem separatentmux
Server am robustesten. Das ist, was dieDokumentationsagt über
Restart=
:In diesem Kontext bedeutet ein sauberer Ausgang einen Ausgangcode von
0
oder eines der SignaleSIGHUP
,SIGINT
,SIGTERM
oderSIGPIPE
, und […]Hinweis:
$?
In einer Shell ist es nur eine Zahl. Nochmal:dieser Link. Wenn Ihrdotnet
System aufgrund eines Signals beendet wird und der Neustart von einem (un-)sauberen Beenden abhängt, können sich die Lösungen, bei denen dersystemd
Beendigungscode direkt abgerufen wird,dotnet
anders verhalten als Lösungen, bei denen dersystemd
Beendigungsstatus von einer zwischengeschalteten Shell abgerufen wird. Recherchieren SieSuccessExitStatus=
, es kann hilfreich sein.
Antwort2
Möglicherweise können Sie RestartForceExitStatus=
die Servicedatei verwenden
Nimmt eine Liste von Beendigungsstatusdefinitionen an, die, wenn sie vom Hauptdienstprozess zurückgegeben werden, automatische Neustarts des Dienstes erzwingen, unabhängig von der mit Restart= konfigurierten Neustarteinstellung. Das Argumentformat ist ähnlich wie RestartPreventExitStatus=.
https://www.freedesktop.org/software/systemd/man/systemd.service.html