スクリプトにエラーが発生した場合、ExecStop=/usr/lib/pick/d3shutdown_custom pick0
systemdはシャットダウンプロセスを中止して状態に戻ることを望みますactive
。
スクリプトがコード4(ユーザー権限不足)で終了すると、systemdはその状態に閉じ込められますdeactivating
。
これは私のシステムサービスファイルです
[Unit]
Description=D3 multivalue database
After=d3_sn.service rslm.service
Requires=rslm.service
Wants=d3_sn.service
[Service]
Type=forking
ExecStart=/usr/bin/d3 -n pick0 -s -a x
ExecStop=/usr/lib/pick/d3shutdown_custom pick0
TimeoutSec=0
RemainAfterExit=true
SuccessExitStatus=11
[Install]
WantedBy=multi-user.target
d3shutdown_custom
これはスクリプトの一部です
log_error() {
echo -e "Error: $1"
echo "Aborting program ... "
echo " "
}
if [ ! -f "$D3_PROPERTIES_FILE" ]; then log_error "File $D3_PROPERTIES_FILE not found."; exit 2; fi
source $D3_PROPERTIES_FILE
export PICKUSER
export PICKUPASS
if d3 -q | grep -q 'not running'; then
exit 11
fi
D3TCL=$(/usr/bin/d3tcl 'listu')
if echo $D3TCL | grep -q 'Bad User or User Password'; then log_error "Bad password"; exit 4; fi
ベストアンサー1
ちょっとトリッキーなリクエストですね。あなたが何かをするときsystemctl stop
、しなければならないそして〜するいつも降りてください。失敗するかもしれませんが、systemd
必ずしなければならないとしても結局は止まるでしょう。FinalKillSignal=(SIGKILL)
〜の後TimeStopSec=(90s)
。
条件が失敗した場合、「終了」や「再開」などの操作は不可能であり、これらの操作は常に可能でなければなりません。
私はこれを達成するための最良の方法は次のとおりです。Conflicts=
条件付きで衝突するデバイスを起動するデバイスとデバイスOnFailure=
。これはあなたがsystemctl stop my-unit
考えを変えなければならないことを意味しますsystemctl start maybe-kill-my-unit
。
これがシャットダウンがどのように機能するかです。私たちは他のユニット、私たちをブロックしませんsystemctl start shutdown.target
。
c.service
人々が直接使用するのを防ぎ、使用をさらにsystemctl stop a.service
強化することができます。RefuseManualStop=yes
。
a.service
[Unit]
Description=Long running service
RefuseManualStop=yes
[Service]
ExecStart=/bin/sleep 60
b.service
[Unit]
Description=Killer of the long running service
Conflicts=a
[Service]
Type=oneshot
ExecStart=/bin/true
c.service
[Unit]
Description=Conditional killer of the long runing service
OnFailure=b
[Service]
Type=oneshot
ExecStart=/usr/local/bin/myscript
以下は実際の例です(c
失敗した場合)。
$ systemctl --user start a
$ systemctl --user start c
Job for c.service failed because the control process exited with error code.
$ systemctl --user status a b c --lines 0
● a.service
Loaded: loaded (.config/systemd/user/a.service; static)
Active: inactive (dead) since Mon 2023-10-09 16:10:18 CEST; 3s ago
● b.service
Loaded: loaded (.config/systemd/user/b.service; static)
Active: inactive (dead) since Mon 2023-10-09 16:10:18 CEST; 3s ago
● c.service
Loaded: loaded (.config/systemd/user/c.service; static)
Active: failed (Result: exit-code) since Mon 2023-10-09 16:10:18 CEST; 3s ago
$ journalctl --user -u a -u b -u c --since "1 minute ago"
Oct 09 16:10:14: Long running service
Oct 09 16:10:18: Starting Conditional killer of the long runing service
Oct 09 16:10:18: c.service: Main process exited, code=exited, status=1/FAILURE
Oct 09 16:10:18: c.service: Triggering OnFailure= dependencies.
Oct 09 16:10:18: Starting Killer of the long running service...
Oct 09 16:10:18: Stopping Long running service...
Oct 09 16:10:18: Finished Killer of the long running service.
成功した例は次のとおりですc
。
$ systemctl --user start a
$ systemctl --user start c
$ systemctl --user status a b c --lines 0
● a.service
Loaded: loaded (.config/systemd/user/a.service; static)
Active: active (running) since Mon 2023-10-09 16:14:45 CEST; 9s ago
● b.service
Loaded: loaded (.config/systemd/user/b.service; static)
Active: inactive (dead)
● c.service
Loaded: loaded (.config/systemd/user/c.service; static)
Active: inactive (dead)
$ journalctl --user -u a -u b -u c --since "1 minute ago"
Oct 09 16:14:45: Started Long running service.
Oct 09 16:14:50: Starting Conditional killer of the long runing service...
Oct 09 16:14:50: Finished Conditional killer of the long runing service.
a
これが失敗すると、c
例は停止します。スクリプトが反転した場合(c
成功した場合は停止する必要があります)、再生できます。SuccessExitStatus=
。
最新バージョンのsystemdがある場合は、次のコマンドを使用してよりエレガントにすることができます。ExecCondition=
結合するOnSuccess=
。これにより、デバイスが故障したままになり、グローバル「ダウングレード」を汚染し、systemctl status
stderrにエラーメッセージを残すのを防ぎます。これを行うには、ExecCondition=
スクリプトを実行してください。成功すればExecStart=
成功OnSuccess=
し、行動を促し、b.service
人を殺しますa.service
。ExecCondition=
失敗するとExecStart=
実行もOnSuccess=
トリガーもされないため、生存が可能ですa.service
。
c.service
[Unit]
OnSuccess=b.service
[Service]
Type=oneshot
ExecCondition=/your-script
ExecStart=/bin/true