我正在将现有的 /etc/init.d 服务转换为 systemd。它似乎可以正常工作,但我遇到了一个奇怪的问题。systemd 服务会顺利地使用命令“systemctl start service_name”启动,并使用“systemctl stop service_name”停止,但它似乎没有干净地停止。底层应用程序会检查它是否已在运行,如果是,则立即终止。这就是正在发生的事情。
以下是旧 /etc/init.d 脚本中的等效代码片段:
kill_process() {
pkill -SIGINT service_name
sleep 1
if [ -n "$(pgrep service_name)" ]; then
pkill -SIGTERM service_name
sleep 1
fi
if [ -n "$(pgrep service_name)" ]; then
pkill -SIGKILL service_name
sleep 1
fi
if [ -z "$(pgrep service_name)" ]; then
rm -f /var/lock/subsys/service_name
fi
}
start() {
action $"Starting Service: " /sbin/service_name
}
stop() {
action $"Stopping Service: " kill_process
}
restart() {
stop
start
}
这是我对 systemd 等效功能的首次尝试:
[Unit]
Description=Service Name
[Service]
ExecStart=/sbin/service_name
[Install]
WantedBy=multi-user.target
我的理解是 systemd 服务将使用 SIGTERM 处理进程终止,但我已经尝试了 KillSignal 和 ExecStop 的其他值。但是,我尚未理解终止行为的这种差异。此外,如果我使用 SIGINT 手动终止应用程序,它也不会干净地终止服务。我想知道 /etc/init.d 是否在幕后执行其他操作。
欢迎提出任何建议。
答案1
我只是想在这篇文章下画一条线,以防其他人感兴趣。
作为服务的一部分运行的 C 应用程序以前使用 fork(),如果 getppid() 尚未为 1(即尚未分叉)。看来,当应用程序由 systemd 运行时,它的父 PID 已经为 1。我们的应用程序以前没有明确的 SIGTERM 处理,但在 /etc/init.d 上下文中对 SIGINT 做出反应时确实正常关闭。我添加了一个特定的 SIGTERM 处理程序,现在服务的行为符合预期。