
私はsystemdユニットファイルを使用してサーバー上で実行されるPythonプロセスを制御します(systemd v247を使用)。
このプロセスは、600秒以内に5回失敗しない限り、失敗の有無にかかわらず、終了後60秒後に再起動する必要があります。
このユニットファイルは、電子メールによる障害通知のために他のサービスに接続されます。
/etc/systemd/system/python-test.service
[Unit]
After=network.target
OnFailure=mailer@%n.service
[Service]
Type=simple
ExecStart=/home/debian/tmp.py
# Any exit status different than 0 is considered as an error
SuccessExitStatus=0
StandardOutput=append:/var/log/python-test.log
StandardError=append:/var/log/python-test.log
# Always restart service 60sec after exit
Restart=always
RestartSec=60
# Stop restarting service after 5 consecutive fail in 600sec interval
StartLimitInterval=600
StartLimitBurst=5
[Install]
WantedBy=multi-user.target
/etc/systemd/system/[email protected]
[Unit]
After=network.target
[Service]
Type=oneshot
ExecStart=/home/debian/mailer.py --to "[email protected]" --subject "Systemd service %I failed" --message "A systemd service failed %I on %H"
[Install]
WantedBy=multi-user.target
OnFailure
基本テスト中、トリガーは非常にうまく機能しました。ただし、ユニットファイルに次のセクションを追加すると、OnFailure
5回連続して失敗した場合にのみ実行されます。
StartLimitInterval=600
StartLimitBurst=5
まだバースト制限に達していない場合でも、プロセスが失敗するたびに通知を受けたいので、これは私が望む動作ではありません。
プロセスの状態を確認する際にバースト制限に達していない場合、出力は異なります。
● python-test.service
Loaded: loaded (/etc/systemd/system/python-test.service; disabled; vendor preset: enabled)
Active: activating (auto-restart) (Result: exit-code) since Thu 2022-12-22 19:51:23 UTC; 2s ago
Process: 1421600 ExecStart=/home/debian/tmp.py (code=exited, status=1/FAILURE)
Main PID: 1421600 (code=exited, status=1/FAILURE)
CPU: 31ms
Dec 22 19:51:23 test-vps systemd[1]: python-test.service: Failed with result 'exit-code'.
その時より
● python-test.service
Loaded: loaded (/etc/systemd/system/python-test.service; disabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Thu 2022-12-22 19:52:02 UTC; 24s ago
Process: 1421609 ExecStart=/home/debian/tmp.py (code=exited, status=1/FAILURE)
Main PID: 1421609 (code=exited, status=1/FAILURE)
CPU: 31ms
Dec 22 19:51:56 test-vps systemd[1]: python-test.service: Failed with result 'exit-code'.
Dec 22 19:52:02 test-vps systemd[1]: python-test.service: Scheduled restart job, restart counter is at 5.
Dec 22 19:52:02 test-vps systemd[1]: Stopped python-test.service.
Dec 22 19:52:02 test-vps systemd[1]: python-test.service: Start request repeated too quickly.
Dec 22 19:52:02 test-vps systemd[1]: python-test.service: Failed with result 'exit-code'.
Dec 22 19:52:02 test-vps systemd[1]: Failed to start python-test.service.
Dec 22 19:52:02 test-vps systemd[1]: python-test.service: Triggering OnFailure= dependencies.
OnFailure
ユニットファイル内でトリガーを変更する方法を説明するものが見つかりません。
プロセスが失敗するたびに電子メールで通知しながらバースト制限を維持する方法はありますか?
答え1
システムサービスを必要に応じて利用するには、いくつかの作業を行う必要があります。 (変更進行中)/etc/systemd/system/python-test.service)。
Restart=always
に変更Restart=on-failure
- この値もサポートされている
StartLimitInterval=600
ようです。StartLimitBurst=5
しかし、に入れる必要があります。を[Unit]
入れると名前を変更できます(代わりに使用)。StartLimitInterval
[Unit]
StartLimitIntervalSec
man systemd.unit
StartLimitIntervalSec
RemainAfterExit=no
セクションに追加してください[Service]
。- セクションに次の行を追加します
[Service]
。TimeoutStopSec=infinity
- スクリプトの環境変数を使用して、
EXIT_STATUS
スクリプトが正常に終了したことを確認します。 - に変更 。
OnFailure=mailer@%n.service
2つOnFailure=mailer@%N.service
の違いは、それを使用すると%N
サフィックスが削除されることです。 - コマンドを使用できるようにサービス
atd
()をインストールして開始します。または、使用しない場合は、別のシステムサービスを作成してサービスを再起動できます。 (この例ではを使用しました)sudo systemctl start atd.service
at
at
relaunch.service
sleep
とに同じ値を使用してくださいRestartSec
。あなたの場合は、この行の睡眠にもRestartSec
以下を含める必要があります。60
60
echo "sleep 60; sudo systemctl start ${1}.service" | at now
- 使用
ExecStart
してExecStopPost=
取得終了ステータス主なプロセス:/home/debian/tmp.py
。ExecStop
以下で使用しないでくださいman systemd.service
。
実行が停止しました =
ExecStop =で指定されたコマンドは、サービスが初めて正常に起動したときにのみ実行されます。サービスがまったく開始されていないか、起動に失敗した場合(例:ExecStart =、ExecStartPre =、またはExecStartPost =で指定されたコマンドが失敗したため)、呼び出されません(「-」プレフィックスが付いていません。上記を参照)。 ) またはタイムアウトしました。サービスが正しく開始されずに再び終了すると、ExecStopPost =と共にコマンドが呼び出されます。
提供する/etc/systemd/system/python-test.serviceしなければならない:
[Unit]
After=network.target
OnFailure=mailer@%N.service
StartLimitBurst=5
StartLimitIntervalSec=600
[Service]
Type=simple
TimeoutStopSec=infinity
ExecStart=/home/debian/tmp.py
ExecStopPost=/bin/bash -c 'echo The Service has exited with values: $$EXIT_STATUS,$$SERVICE_RESULT,$$EXIT_CODE'
ExecStopPost=/home/debian/bin/checkSuccess "%N"
# Any exit status different than 0 is considered as an error
SuccessExitStatus=0
StandardOutput=append:/tmp/python-out-test.log
StandardError=append:/tmp/python-err-test.log
# Always restart service 60sec after exit
Restart=on-failure
RestartSec=60
RemainAfterExit=no
[Install]
WantedBy=multi-user.target
そして/Home/Debian/bin/checkSuccess以下が必要です。
解決策1:使用at
コマンド:
#!/bin/bash
if [ "$EXIT_STATUS" -eq 0 ]
then
echo "sleep 60; sudo systemctl start ${1}.service" | at now
exit 0
else
systemctl start "mailer@${1}.service"
exit 0
fi
解決策2:別のシステムサービスを使用してください。
#!/bin/bash
if [ "$EXIT_STATUS" -eq 0 ]
then
systemctl start relaunch.service
else
systemctl start "mailer@${1}.service"
fi
exit 0
そして、relaunch.service
次のものが必要です。
[Unit]
Description=Relaunch Python Test Service
[Service]
Type=simple
RemainAfterExit=no
ExecStart=/bin/bash -c 'echo Delay; sleep 10 ; systemctl start python-test.service'
"$EXIT_STATUS"
systemdサービスによって設定された変数は、終了状態によって決まります/home/debian/tmp.py
。
${1}
単位を表す名前:python-test
行のスクリプトに渡します/home/debian/bin/checkSuccess "%N"
。
メモ:
'echo The Service %n has exited with values: $$EXIT_STATUS,$$SERVICE_RESULT,$$EXIT_CODE'
次のコマンドを使用すると、リアルタイムでログを確認できます。
tail -f /tmp/python-out-test.log
relaunch.service
基本サービスを停止するには、ソリューション2(with)を使用している場合は、次の手順を実行する必要があります。
sudo systemctl stop relaunch.service
#Might not be necessary but you stop python service too:
# sudo systemctl stop python-test.service