使用 systemd 配置 java 守护进程

使用 systemd 配置 java 守护进程

我在工作中使用这个定义systemd

 [Unit]
 Description=Some job

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

 [Install]
 WantedBy=multi-user.target

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

 #!/bin/sh

 cd /home/user/tmp/testout
 nohup java -jar /home/user/programming/tests/java/core/SocketTest/SocketTest.jar </dev/null >/dev/null &

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

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

所以一切看起来都很好而且花花公子

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

答案1

以下是一些小的修改:

  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

笔记:

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

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

相关内容