考虑这种场景:Systemd Type=forking 服务启动一个 shell 脚本,该脚本又启动另一个脚本并退出,然后启动实际的服务/守护进程。
现在,systemd 将在第一个 shell 脚本退出后立即认为服务已启动,并将第二个 shell 脚本视为服务或查找 PID 文件(如果服务文件中提到了该文件)。我的困惑是,第一个脚本在第二个脚本创建 PID 文件之前就退出了,而第二个脚本在实际服务进程最终启动时大约半分钟后退出。
虽然理论上我可以合并这些链式启动脚本,但它们是随我为其创建 systemd 服务文件的服务一起提供的,因此为了便于更新,我宁愿不将它们混合在一起。
所以基本上的问题是:如何处理 systemd 服务中的链式分叉进程,以便只有链中的最后一个分叉被 systemd 考虑/监控?
供参考:导致该问题的软件是 JetBrains 的 CI 服务器 TeamCity 的最新版本。
据我所知,StackExchange 的用户喜欢代码示例,因此我们使用了一个简化的无意义版本:teamcity-server.service(Systemd 服务文件):
[Unit]
Description=TeamCity server
After=network.target
[Service]
EnvironmentFile=/etc/conf.d/teamcity
ExecStart=/opt/teamcity/bin/teamcity-server.sh start
ExecStop=/opt/teamcity/bin/teamcity-server.sh stop
Type=forking
PIDFile=/opt/teamcity/logs/teamcity.pid
Restart=no
TimeoutSec=30
RemainAfterExit=yes
User=teamcity
[Install]
WantedBy=multi-user.target
teamcity-server.sh(这不是真正的脚本,仅展示如何执行链式脚本):
#!/bin/sh
sh "script2.sh" "run" "$@" &
wait $!
EXIT_CODE=$?
exit $EXIT_CODE
script2.sh(这也不是一个真正的脚本,只是展示我们如何在此启动 java 守护进程):
#!/bin/sh
PIDFILE = "/opt/teamcity/logs/teamcity.pid"
java -jar somejavadaemon.jar
tc_pid=$?
echo $tc_pid > $PIDFILE