私は最近、ネットワーク稼働時間をテストできるUbuntu LTSサーバーにサービスを作成しました。スクリプト自体は期待どおりに機能しますが、それをサービスに切り替えようとしたときにいくつかの問題が発生すると、サービスが開始されるとすぐに(stopコマンドを介して)それ自体が停止します。
制御ファイル:
#!/bin/bash
case "$1" in
start)
/home/user/network_script/network_script.sh &
echo $!>/var/run/network_script.pid
;;
stop)
kill `cat /var/run/network_script.pid`
rm /var/log/network_output.status
rm /var/run/network_script.pid
;;
restart)
$0 stop
$0 start
;;
status)
if [ -e /var/run/network_script.pid ]; then
echo network_script.sh is running, pid=`cat /var/run/network_script.pid`
echo /var/log/network_script.status
else
echo network_script.sh is NOT running
exit 1
fi
;;
*)
echo "Usage: $0 {start|stop|status|restart}"
esac
exit 0
システムファイル:
[Unit]
Description=Network Script
[Service]
ExecStart=/home/user/network_script/network_script_controls.sh start
ExecStop=/home/user/network_script/network_script_controls.sh stop
ExecRestart=/home/user/network_script/network_script_controls.sh restart
ExecStatus=/home/user/network_script/network_script_controls.sh status
[Install]
WantedBy=multi-user.target
ステータス出力:
network_script.service - Network Script
Loaded: loaded (/etc/systemd/system/network_script.service; enabled; vendor preset: enabled)
Active: inactive (dead) since Tue 2023-01-03 14:07:46 EST; 8s ago
Process: 25131 ExecStart=/home/user/network_script/network_script_controls.sh start (code=exited, status=0/S>
Process: 25133 ExecStop=/home/user/network_script/network_script_controls.sh stop (code=exited, status=0/SUC>
Main PID: 25131 (code=exited, status=0/SUCCESS)
CPU: 9ms
Jan 03 14:07:46 greengoblin systemd[1]: Started Network Script.
Jan 03 14:07:46 greengoblin network_script_controls.sh[25136]: rm: cannot remove '/var/log/network_output.status>
Jan 03 14:07:46 greengoblin systemd[1]: network_script.service: Deactivated successfully.
答え1
Type=forking
セクションに追加してください[Service]
。 、
~からマニュアルページ:
ブランチに設定されている場合、ExecStart =で設定されたプロセスは開始の一部としてブランチ()を呼び出す必要があります。起動が完了し、すべての通信チャネルが確立されると、親プロセスが終了すると予想されます。子プロセスは引き続き基本サービスプロセスとして実行され、親プロセスが終了すると、サービスマネージャはそのユニットが開始されたと見なす。これは既存のUNIXサービスの動作です。この設定を使用する場合は、systemdがサービスの基本プロセスを確実に識別できるように、PIDFile =オプションも使用することをお勧めします。親プロセスが終了すると、systemd は引き続き後続のユニットを起動します。
また、プロセスがまだ実行中であるか、競合が発生しているかどうかを確認できるように、systemdにPIDファイルを知らせることをお勧めします。
マニュアルページには次のように表示されますPIDFile=
。
サービスを参照するPIDファイルへのパスを使用します。このオプションは、Type = このブランチに設定されたサービスに推奨されます。指定されたパスは通常/run/の下のファイルを指します。相対パスを指定すると、前に/run/が付けられます。サービスの開始後、サービス管理者はこのファイルからサービス基本プロセスのPIDを読み取ります。サービスマネージャはここで設定されたファイルに書き込まれませんが、ファイルがまだ存在する場合は、サービスが終了した後にファイルを削除します。 PIDファイルは、権限のあるユーザーが所有する必要はなく、権限のないユーザーが所有している場合は、追加のセキュリティ制限が適用されます。ファイルは、所有するファイルへのシンボリックリンク(直接または間接)にすることはできません。他のユーザーのPIDファイルとすでにそのサービスに属するプロセスを参照する必要があります。
最新のプロジェクトではPIDファイルを避ける必要があります。サービスの主なプロセスを決定し、不要なフォークを避けるためにPIDファイルを使用する必要がないように、可能な場合はType = notifyまたはType = simpleを使用してください。
これは、お客様のサービスが次のようになることを意味します。
[Service]
Type=forking
PIDFile=/var/run/network_script.pid
ExecStart=/home/user/network_script/network_script_controls.sh start
ExecStop=/home/user/network_script/network_script_controls.sh stop
ExecRestart=/home/user/network_script/network_script_controls.sh restart
ExecStatus=/home/user/network_script/network_script_controls.sh status
つまり、最後の段落を詳しく見てくださいPIDFile=
。 systemdを使用しているので、PIDを直接追跡する必要はありません。これにより、スクリプトを分岐する必要がなくなります。 Systemdはこれを自動的に実行します。
私はあきらめて/home/user/network_script/network_script_controls.sh
このユニットファイルを使います:
[Unit]
Description=Network Script
[Service]
Type=simple
ExecStart=/home/user/network_script/network_script.sh
[Install]
WantedBy=multi-user.target