configure java daemon with systemd
16,859
Here's some minor modifications:
- Since it listens on a network socket, make it a dependency of
network.target
. -
nohup
is not needed sincesystemd
will daemonize the executable for you. - I think a separate shell script would be an overkill, so just merge it into the service file.
- Redirection (
< /dev/null
and so forth) isn't needed since systemd sets up an appropriate standard I/O context. Indeed, if you take the redirection out systemd will log anything sent to standard output by the Java program in its journal, with no special logging mechanism required. - Running asynchonously from the invoking shell (
&
) isn't needed or appropriate. - There's a specific behaviour pattern required by
Type=forking
, and if it isn't followed by the dæmon things go wrong. So try forType=simple
(orType=notify
).
So the service file looks like this:
[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
Notes:
- You cannot just use
java
as the name of the program to run. systemd doesn't searchPATH
for executables, and the name of the executable given toExecStart
must be absolute. So if you want path searching you have to invoke via a shell or/usr/bin/env
. We choose/bin/sh
here. - Because this is
Type=simple
the shell mustexec
Java, not run it as a child process. systemd controls the service through the main process, and that needs to be Java, not a parent shell process. - Because this isn't invoking the Java executable directly, systemd will put the name
sh
in its journal as the service name. See How to avoid /usr/bin/env being marked in systemd logs as the executable for more on this.
As far as I know, there is no special caveat of running Java application with Systemd.
Related videos on Youtube
Author by
lash
Updated on September 18, 2022Comments
-
lash over 1 year
I'm using this definition for a
systemd
job:[Unit] Description=Some job [Service] ExecStart=/usr/local/sbin/somejob User=dlt Type=forking [Install] WantedBy=multi-user.target
The script is called is as follows (calling a simple routine that listens on a tcpip socket and appends the input to a file):
#!/bin/sh cd /home/user/tmp/testout nohup java -jar /home/user/programming/tests/java/core/SocketTest/SocketTest.jar </dev/null >/dev/null &
After
systemctl start somejob
process shows as running, withinit
as its parent: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
After performing
systemctl stop somejob
the process doesn't show anymore (and the port is closed).So everything seems fine and dandy
My question is: Is this an acceptable solution for running a java daemon with
systemd
, or are there caveats, and thus other more stable or secure ways to go about achieving this? -
Yun-Chih Chen over 7 yearsNice head up. I can only manage to fix problem 1. How do you go about fixing Prob 2,3?
-
JdeBP over 7 yearsSee the answer as edited.
-
faho over 7 yearsI don't think the sh is necessary here.
-
black sensei about 6 yearsHello @Yun-ChihChen how do you stop the process. What does ExecStrop would look like? I have been using init.d along with a pid file but found this easier. So I needed to make sure I know how to stop etc. Thanks
-
user149408 about 4 years@blacksensei Possibly not at all. If
ExecStop
is not specified, systemd stops a service by sending aSIGINT
to that process. Not sure if it works the same way with a shell in between, though.