我在/etc/systemd/system中编写了这个服务,名为nexusiq.service
:
[Unit]
Description=Nexus IQ Service
After=network.target
[Service]
Type=simple
ExecStart=/etc/init.d/nexus-iq-server start
ExecStop=/etc/init.d/nexus-iq-server stop
User=root
Restart=on-abort
TimeoutSec=600
[Install]
WantedBy=multi-user.target
/etc/init.d 中的脚本nexus-iq-server
在 ExecStart 和 ExecStop 中调用,具体取决于我是否给出“start”或“stop”作为参数,执行以下操作:
NEXUS_IQ_SERVER_HOME=/apps/nexus/nexus-iq-server
VERSION=1.127.0-01
JAVA_OPTIONS="-Xmx4096m -XX:+UseG1GC"
RUN_AS_USER=root
do_start()
{
cd $NEXUS_IQ_SERVER_HOME
su -m $RUN_AS_USER --command "java $JAVA_OPTIONS -jar nexus-iq-server-$VERSION.jar server config.yml 2> stderr.log &"
echo "Started nexus-iq-server"
}
do_console()
{
cd $NEXUS_IQ_SERVER_HOME
su -m $RUN_AS_USER --command "java $JAVA_OPTIONS -jar nexus-iq-server-$VERSION.jar server config.yml 2> stderr.log"
}
do_stop()
{
pid=`ps aux | grep nexus-iq-server | grep '.jar server' | grep -vE '(stop|grep)' | awk '{print $2}'`
kill $pid
echo "Killed nexus-iq-server - PID $pid"
}
do_usage()
{
echo "Usage: nexus-iq-server [console|start|stop]"
}
case $1 in
console)
do_console
;;
start)
do_start
;;
stop)
do_stop
;;
*)
do_usage
;;
esac
我已启用该服务。
当我运行命令时:
systemctl start nexusiq
正确调用分配给 ExecStart 的命令。但是,如果我运行该命令systemctl stop nexusiq
,则不会调用分配给 ExecStop 的命令。
此外,如果我运行命令systemctl status nexusiq
,看起来该服务处于非活动状态:
● nexusiq.service - Nexus IQ Service
Loaded: loaded (/etc/systemd/system/nexusiq.service; enabled; vendor preset: disabled)
Active: inactive (dead) since Wed 2021-11-17 12:56:03 CET; 16s ago
Process: 14806 ExecStop=/etc/init.d/nexus-iq-server stop (code=exited, status=0/SUCCESS)
Process: 14800 ExecStart=/etc/init.d/nexus-iq-server start (code=exited, status=0/SUCCESS)
Main PID: 14800 (code=exited, status=0/SUCCESS)
Nov 17 12:56:03 nexusiq2 systemd[1]: Started Nexus IQ Service.
Nov 17 12:56:03 nexusiq2 su[14801]: (to root) root on none
Nov 17 12:56:03 nexusiq2 nexus-iq-server[14800]: Started nexus-iq-server
谁能向我解释一下造成这种情况的原因以及如何解决它?
答案1
你需要Type=forking
而不是Type=simple
.
手册页说:
- 如果设置为 simple(如果指定了 ExecStart=,但 Type= 和 BusName= 均未指定,则为默认值),服务管理器将认为该单元在主服务进程分叉后立即启动。预计ExecStart=配置的进程是服务的主进程。在此模式下,如果进程向系统上的其他进程提供功能,则应在服务启动之前安装其通信通道(例如,由 systemd 通过套接字激活设置套接字),因为服务管理器将立即开始执行以下操作-up 单元,在创建主服务进程之后、执行服务的二进制文件之前。请注意,这意味着即使无法成功调用服务的二进制文件(例如,因为所选的 User= 不存在,或者服务二进制文件丢失),简单服务的 systemctl start 命令行也会报告成功。
- 如果设置为 forking,则预计使用 ExecStart= 配置的进程将调用 fork() 作为其启动的一部分。当启动完成并且所有通信通道都建立后,父进程预计将退出。子进程继续作为主服务进程运行,当父进程退出时,服务管理器会认为该单元已启动。这是传统 UNIX 服务的行为。如果使用此设置,建议同时使用PIDFile=选项,以便systemd能够可靠地识别服务的主进程。一旦父进程退出,systemd 将继续启动后续单元。
总而言之,当/etc/init.d/nexus-iq-server start
结束时,systemd things 你的服务就完成了。因此它认为它处于非活动状态(已停止)。 systemd
会将残留的 java 进程视为需要清理并终止的进程。 systemctl stop
不会执行任何操作,因为设备已经停止。
使用Type=forking
告诉 systemdExecStart=
预计会产生一个进程并退出。该生成的进程成为 systemd 跟踪的主要 PID。