使用 systemd 配置 java 守护进程

las*_*ash 12 java systemd daemon

我将这个定义用于systemd工作:

 [Unit]
 Description=Some job

 [Service]
 ExecStart=/usr/local/sbin/somejob
 User=dlt
 Type=forking

 [Install]
 WantedBy=multi-user.target
Run Code Online (Sandbox Code Playgroud)

脚本调用如下(调用一个简单的例程,侦听 tcpip 套接字并将输入附加到文件):

 #!/bin/sh

 cd /home/user/tmp/testout
 nohup java -jar /home/user/programming/tests/java/core/SocketTest/SocketTest.jar </dev/null >/dev/null &
Run Code Online (Sandbox Code Playgroud)

之后systemctl start somejob的过程显示为下运行,同时init作为其父:

 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
Run Code Online (Sandbox Code Playgroud)

执行systemctl stop somejob该过程后不再显示(并且端口已关闭)。

所以一切看起来都很好

我的问题是:这是运行 java 守护进程的可接受的解决方案systemd,还是有警告,以及其他更稳定或安全的方法来实现这一目标?

Yun*_*hen 17

这里有一些小的修改:

  1. 由于它侦听网络套接字,因此使其成为network.target.
  2. nohup不需要,因为systemd它将为您守护可执行文件。
  3. 我认为单独的 shell 脚本会有点矫枉过正,所以只需将其合并到服务文件中即可。
  4. < /dev/null由于 systemd 设置了适当的标准 I/O 上下文,因此不需要重定向(等等)。实际上,如果您取消重定向 systemd 会将 Java 程序发送到标准输出的任何内容都记录在其日志中,而无需特殊的日志记录机制。
  5. 从调用 shell ( &)异步运行是不需要或不合适的。
  6. 需要一个特定的行为模式Type=forking,如果守护进程没有遵循它,事情就会出错。所以尝试Type=simple(或Type=notify)。

所以服务文件看起来像这样:

[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
Run Code Online (Sandbox Code Playgroud)

笔记:

  1. 您不能仅用java作要运行的程序的名称。systemd 不搜索PATH可执行文件,并且给定的可执行文件的名称ExecStart必须是绝对的。因此,如果您想进行路径搜索,则必须通过 shell 或/usr/bin/env. 我们选择/bin/sh这里。
  2. 因为这是JavaType=simple必须的shell exec,不能将它作为子进程运行。systemd 通过主进程控制服务,这需要是 Java,而不是父 shell 进程。
  3. 因为这不是直接调用 Java 可执行文件,所以 systemd 会将名称sh作为服务名称放入其日志中。有关更多信息,请参阅如何避免在 systemd 日志中将 /usr/bin/env 标记为可执行文件

据我所知,使用 Systemd 运行 Java 应用程序没有特别的警告。