我正在将这个定义用于系统工作:
[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 &
在systemctl启动后,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后,该进程不再显示(并且端口已关闭).
所以一切看起来都很好,花花公子
我的问题是:这是一个可以接受的解决方案,用于运行带有systemd的java守护进程,还是有警告,以及其他更稳定或安全的方法来实现这一目标?
解决方法:
这是一些小修改:
>由于它侦听网络套接字,因此将其作为network.target的依赖项.
>不需要nohup,因为systemd会为您守护可执行文件.
>我认为单独的shell脚本是一种过度杀伤,所以只需将其合并到服务文件中即可.
>由于systemd设置了适当的标准I / O上下文,因此不需要重定向(< / dev / null等).实际上,如果你重新定向,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,shell必须执行Java,而不是将其作为子进程运行. systemd通过主进程控制服务,这需要是Java,而不是父shell进程.
>因为这不是直接调用Java可执行文件,所以systemd会将名称sh作为服务名称放在其日志中.有关详细信息,请参阅How to avoid /usr/bin/env being marked in systemd logs as the executable.
据我所知,使用Systemd运行Java应用程序没有特别的警告.
标签:java,systemd,daemon
来源: https://codeday.me/bug/20190809/1632166.html