我在工作中使用这个定义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
以下是一些小的修改:
- 由于它侦听网络套接字,因此使其成为
network.target
. nohup
不需要,因为systemd
将为您守护可执行文件。- 我认为单独的 shell 脚本太过分了,所以只需将其合并到服务文件中即可。
- 重定向(
< /dev/null
由于 systemd 设置了适当的标准 I/O 上下文,因此不需要等等)。事实上,如果你采取重定向出去systemd 将在其日志中记录 Java 程序发送到标准输出的任何内容,无需特殊的日志记录机制。 &
不需要也不适合从调用 shell () 异步运行。- 需要一个特定的行为模式
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
笔记:
- 您不能仅用作
java
要运行的程序的名称。 systemd 不搜索PATH
可执行文件,并且给出的可执行文件的名称ExecStart
必须是绝对的。因此,如果您想要路径搜索,则必须通过 shell 或/usr/bin/env
.我们选择/bin/sh
这里。 - 因为这是
Type=simple
必须Java的shellexec
,不能将其作为子进程运行。 systemd 通过主进程控制服务,并且需要是 Java,而不是父 shell 进程。 - 因为这不是直接调用 Java 可执行文件,所以 systemd 会输入名称
sh
作为服务名称放入其日志中。看如何避免 /usr/bin/env 在 systemd 日志中被标记为可执行文件了解更多相关信息。
据我所知,使用 Systemd 运行 Java 应用程序没有特殊的警告。