
Ich verwende diese Definition für einen systemd
Job:
[Unit]
Description=Some job
[Service]
ExecStart=/usr/local/sbin/somejob
User=dlt
Type=forking
[Install]
WantedBy=multi-user.target
Das Skript wird wie folgt aufgerufen (Aufruf einer einfachen Routine, die auf einem TCP/IP-Socket lauscht und die Eingabe an eine Datei anhängt):
#!/bin/sh
cd /home/user/tmp/testout
nohup java -jar /home/user/programming/tests/java/core/SocketTest/SocketTest.jar </dev/null >/dev/null &
Nachdem systemctl start somejob
der Prozess als ausgeführt angezeigt wird, mit init
dem übergeordneten Prozess:
user@CANTANDO ~$ ps -u dlt eo pid,ppid,command
PID PPID COMMAND
8718 1 java -jar /home/user/programming/tests/java/core/SocketTest/SocketTest.jar
Nach der Durchführung systemctl stop somejob
wird der Vorgang nicht mehr angezeigt (und der Port ist geschlossen).
Also alles scheint in Ordnung zu sein
Meine Frage ist: Ist das einakzeptable Lösungzum Ausführen eines Java-Daemons mit systemd
, oder gibt es Einschränkungen und daher andere stabilere oder sicherere Möglichkeiten, dies zu erreichen?
Antwort1
Hier sind einige kleinere Änderungen:
- Da es auf einem Netzwerk-Socket lauscht, machen Sie es zu einer Abhängigkeit von
network.target
. nohup
ist nicht erforderlich, dasystemd
die ausführbare Datei für Sie als Daemon ausgeführt wird.- Ich denke, ein separates Shell-Skript wäre übertrieben, also integrieren Sie es einfach in die Servicedatei.
- Eine Umleitung (
< /dev/null
usw.) ist nicht erforderlich, da systemd einen geeigneten Standard-E/A-Kontext einrichtet. Tatsächlich, wenn Sie die Umleitung nehmenaussystemd protokolliert alles, was vom Java-Programm an die Standardausgabe gesendet wird, in seinem Journal. Dafür ist kein spezieller Protokollierungsmechanismus erforderlich. - Eine asynchrone Ausführung von der aufrufenden Shell (
&
) aus ist weder erforderlich noch sinnvoll. - Es gibt ein bestimmtes Verhaltensmuster, das von verlangt wird
Type=forking
, und wenn der Dæmon es nicht befolgt, geht etwas schief. Versuchen Sie es also mitType=simple
(oderType=notify
).
Die Servicedatei sieht also folgendermaßen aus:
[Unit]
Description=Some job
After=network.target
[Service]
WorkingDirectory=/home/user/tmp/testout
SyslogIdentifier=SocketTest
ExecStart=/bin/sh -c "exec java -jar /home/user/programming/tests/java/core/SocketTest/SocketTest.jar"
User=dlt
Type=simple
[Install]
WantedBy=multi-user.target
Anmerkungen:
- Sie können nicht einfach
java
als Namen des auszuführenden Programms verwenden. systemd sucht nichtPATH
nach ausführbaren Dateien und der Name der angegebenen ausführbaren DateiExecStart
muss absolut sein. Wenn Sie also eine Pfadsuche wünschen, müssen Sie über eine Shell oder aufrufen/usr/bin/env
. Wir wählen/bin/sh
hier. - Da es sich hierbei um
Type=simple
eine Shellexec
handelt, muss diese in Java ausgeführt werden und darf nicht als untergeordneter Prozess ausgeführt werden. systemd steuert den Dienst über den Hauptprozess, und dieser muss in Java ausgeführt werden und darf kein übergeordneter Shell-Prozess sein. - Da dies nicht direkt die Java-Programmdatei aufruft, trägt systemd den Namen
sh
als Dienstnamen in sein Journal ein. SieheSo verhindern Sie, dass /usr/bin/env in Systemd-Protokollen als ausführbare Datei markiert wirdfür weitere Informationen.
Soweit ich weiß, gibt es keine besonderen Einschränkungen beim Ausführen von Java-Anwendungen mit Systemd.