/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 アプリケーションは、getppid() がまだ 1 でない場合 (つまり、まだフォークされていない場合)、以前は fork() を使用していました。アプリケーションが systemd によって実行されると、すでに親 PID が 1 になっているようです。私たちのアプリケーションは以前は明示的な SIGTERM 処理を行っていませんでしたが、/etc/init.d のコンテキストで SIGINT に反応すると正常にシャットダウンしました。特定の SIGTERM ハンドラーを追加したところ、サービスは期待どおりに動作するようになりました。

関連情報