Warum weiß systemd nicht, ob ein Dienst fehlgeschlagen ist?

Warum weiß systemd nicht, ob ein Dienst fehlgeschlagen ist?

Ich versuche, Spring-Boot-Anwendungen (die von jemand anderem entwickelt wurden – ich bin kein Java-Programmierer) auf Ubuntu 18.04 bereitzustellen. Der Entwickler hat zuvor symbolische Links hinzugefügt, /etc/init.dum den Dienst zu aktivieren – er startet beim Booten einwandfrei. Wenn der Dienst jedoch anschließend fehlschlägt, meldet systemd immer noch, dass er ausgeführt wird:

[email protected]:/var/log/apps# systemctl status crm-service
● crm-service.service - LSB: crm-service
   Loaded: loaded (/etc/init.d/crm-service; generated)
   Active: active (exited) since Wed 2020-04-15 12:27:15 BST; 3h 56min ago
     Docs: man:systemd-sysv-generator(8)
  Process: 8656 ExecStop=/etc/init.d/crm-service stop (code=exited, status=0/SUCCESS)
  Process: 8703 ExecStart=/etc/init.d/crm-service start (code=exited, status=0/SUCCESS)

Apr 15 12:27:15 example.com systemd[1]: Starting LSB: crm-service...
Apr 15 12:27:15 example.com crm-service[8703]: /var/services/crm-service.conf: line 1: -Xms96M: command not found
Apr 15 12:27:15 example.com crm-service[8703]: Started [8747]
Apr 15 12:27:15 example.com systemd[1]: Started LSB: crm-service.

Während ich sehe,dieselbe Systemd-Unit-DateiEs gibt überall im Internet Beiträge zu Springboot, aber ich kann dort nichts finden, was dieses Problem wahrscheinlich lösen würde.

  1. Wie kann ich systemd dazu bringen, den wahren Status des Dienstes anzuzeigen? (es wird ein Abhörsocket geöffnet, aber auf einem zufällig ausgewählten hohen Port)
  2. Gibt es eine Möglichkeit, systemd dazu zu bringen, es zu versuchen?sanftum einen Dienst neu zu starten, von dem es weiß, dass er fehlgeschlagen ist?

Antwort1

Systemd hat viele Kritiker und viele davon sind ganz okay, aber das ist es nicht.Systemd kann alle aus dem Startskript geforkten (oder geklonten) Prozesse und Threads verfolgen und den Dienst als inaktiv betrachten, wenn keiner davon übrig geblieben ist.

Das erste Problem, das ich sehe: systemd verwendet keine Start-/Stopp-Skripte /etc/init.d, es ist nur ein Kompatibilitäts-Add-on dafür. Stattdessen verwendet systemd Unit-Dateien, also eine Konfigurationsdatei für alle seine Dienste.

Das systemd sysv init compat-Modul generiert effektiv eine Unit-Datei für alle Dienste in /etc/init.d. Dies ist nicht immer in Ordnung, da den Init-Skripten die erforderlichen Informationen fehlen (oder es unmöglich ist, sie daraus zu extrahieren).

Dieses Kompatibilitätsmodul funktioniert so, dass systemd das Init-Skript als fehlgeschlagen betrachtet und den Dienst somit als nicht funktionsfähig ansieht, wenn sein Exit-Code ungleich Null ist. Ein Exit-Code von Null bedeutet eine erfolgreiche Ausführung. Wenn das Init-Skript fehlerhaft ist und selbst bei einem Fehler einen Exit-Code von Null ausgibt, betrügt es systemd.

Die wahrscheinlichste Ursache für den Fehler Ihres Init-Skripts ist, dass es den Prozess im Hintergrund startet und dann immer mit Null beendet wird. Meine allgemeine Erfahrung mit den meisten Init-Skripten, die von benutzerdefinierten Anbietern geschrieben wurden, ist, dass … die meisten von ihnen möglicherweise erheblichen Verbesserungsbedarf haben. Vertrauen Sie ihnen nicht, schauen Sie, was sie tun, und beheben Sie sie. In Ihrem Fall wäre es am besten, zu prüfen,

  • So starten Sie Ihre Java-App
  • Wo beginnt es
  • Als welcher Benutzer startet es

Und reproduzieren Sie die gleiche Funktionalität mit einer Unit-Datei.

Es gibt keine Möglichkeit, Initskripte von systemd aus automatisch neu zu starten, aber es ist über Unit-Dateien möglich.

Beachten Sie, dass es sich auch bei einem zufälligen Absturz eines Java-Programms um ein schwerwiegendes Problem handelt. Alle vernünftigen Java-Frameworks behandeln ihre eigenen schwerwiegenden Fehler korrekt (sie fangen alle Ausnahmen ab, protokollieren sie und fahren fort).

Ein weiterer sehr wahrscheinlicher Fehler im Init-Skript ist, dass es Ihre JVM nicht findet (höchstwahrscheinlich: /usr/bin/java) und sie daher durch eine leere Zeichenfolge ersetzt, was dazu führt, dass es versucht, die JVM-Flags als Shell-Befehl zu starten. Offensichtlich gibt es -Xms96Min Ihrem System keinen Befehl, aber ein /usr/bin/java -Xms96M ...würde funktionieren.

Eine Beispiel-Unit-Datei für eine Spring-Boot-App:

[Unit]
Description=Crm Spring Boot App Example
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/java -Xms96M ...other flags... your.spring.boot.jar
User=exampleuser
Group=examplegroup
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=exampleapp
WorkingDirectory=/path/to/app/home

[Install]
WantedBy=multi-user.target
Alias=exampleapp.service

Diese Unit-Datei leitet auch die Standardausgabe und Fehler des Java-Prozesses in das Syslog um.

Um die App automatisch neu zu starten, geben Sie

RestartSec=5s
Restart=on-failure

in den [Service]Abschnitt.

Es gibt ein systemd-Tutorial aufGoLinuxCloud.com.

verwandte Informationen