将 /etc/init.d 服务转换为 systemd

将 /etc/init.d 服务转换为 systemd

我正在将现有的 /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 处理程序,现在服务的行为符合预期。

相关内容