我有这个systemd单元文件来启动播放应用程序:
# Systemd unit file for playapp
[Unit]
Description=Run Server for playapp
Wants=syslog.target network.target
After=network.target
[Service]
Type=simple
PIDFile=/opt/playapp/play.pid
ExecStart=/opt/playapp/bin/playapp
ExecStop=/bin/kill $MAINPID
Restart=always
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
Type=simple
的启动失败,则systemctl start playapp.service
没有反馈意见。Type=forking
会出错,但如果启动时没有错误,则systemctl start playapp.service
会保留在shell的前台。使用systemd启动播放应用程序的最佳方法是什么? (如果启动不成功,则显示错误消息)
答案 0 :(得分:1)
没有简单的方法:服务只是用许多参数启动java。如果事情失败(通常在DI初始化期间),服务终止。然而,该服务(读取:java的启动)是成功的:它只是在启动期间终止。
Systemd注意到,并在需要时重新启动它。但是,该错误指向Play日志文件,systemd没有通知。我们只是接受了这个事实,并且如果需要就尾随(实际上,我们将所有日志记录重定向到中央系统服务器,但这只是一个实现细节)。
答案 1 :(得分:1)
这里的问题是systemd不知道等待该进程出错的时间。
对于“ type = simple”,systemd派生一个进程,然后在后台运行该进程。由于systemd无法知道何时完成初始化,并且初始化可能会花费任意长时间,因此systemd只需启动服务并立即返回即可。
一个正常的解决方案是使用“ type = forking”,然后让您的程序进行派生,并且只有在初始化成功完成并且我们知道守护程序可以运行时才进行派生。 Systemd等待分支过程退出,并将其解释为意味着初始化已完成,然后可以在命令行上向您提供反馈。由于playapp可能并非设计为像这样进行分叉,因此您不能立即使用“ type = forking”。
另一种解决方案是使用“ type = notify”,其中守护进程不进行派生,而是在成功初始化后向systemd发送消息。然后,Systemd可以等待。由于我假设playapp也不是为此设计的,因此也不能立即使用。
但是您可以做的是编写您自己的fork shell脚本,该脚本会派出一个playapp进程。像这样:
#!/bin/bash
/bin/playapp &
PID=$!
sleep 2
if [ -n "$PID" -a -e /proc/$PID ]; then
echo "process $PID exists"
exit 0
else
echo "process $PID doesn't exist"
exit 1
fi
(请记住chmod +x
)。在这里,您应该将“ sleep 2”替换为您猜测playapp初始化所需的时间。如果playapp死得更快,甚至可能会形成一个循环,该循环会更快地退出。
如果您随后使用ExecStart=/local/bin/thescript.sh
和Type=forking
制作了服务文件,则它似乎可以工作。我不必指定任何PID文件即可在测试中正常工作。我假设由于分支过程是脚本的子级,因此systemd会自动找出PID。
我测试过的测试系统服务看起来像这样(我在/bin/sleep 3 &
中有一个/local/bin/thescript.sh
,而不是playapp
):
# Systemd unit file for playapp
[Unit]
Description=Run Server for playapp
Wants=syslog.target network.target
After=network.target
[Service]
Type=forking
ExecStart=/local/bin/thescript.sh
[Install]
WantedBy=multi-user.target