依存関係が失敗した場合は、systemdサービスを再起動してください。

依存関係が失敗した場合は、systemdサービスを再起動してください。

依存関係の1つが起動時に失敗するが再試行後に成功した場合、サービスの再起動を処理する正しい方法は何ですか?

これは問題をより明確にするために設計された再現です。

サービス(シミュレーションは最初の試行で失敗し、2回目の試行で成功します。)

[Unit]
Description=A

[Service]
ExecStartPre=/bin/sh -x -c "[ -f /tmp/success ] || (touch /tmp/success && sleep 10)"
ExecStart=/bin/true
TimeoutStartSec=5
Restart=on-failure
RestartSec=5
RemainAfterExit=yes

b.サービス(A開始後成功)

[Unit]
Description=B
After=a.service
Requires=a.service

[Service]
ExecStart=/bin/true
RemainAfterExit=yes
Restart=on-failure
RestartSec=5

bから始めましょう:

# systemctl start b
A dependency job for b.service failed. See 'journalctl -xe' for details.

丸太:

Jun 30 21:34:54 debug systemd[1]: Starting A...
Jun 30 21:34:54 debug sh[1308]: + '[' -f /tmp/success ']'
Jun 30 21:34:54 debug sh[1308]: + touch /tmp/success
Jun 30 21:34:54 debug sh[1308]: + sleep 10
Jun 30 21:34:59 debug systemd[1]: a.service start-pre operation timed out. Terminating.
Jun 30 21:34:59 debug systemd[1]: Failed to start A.
Jun 30 21:34:59 debug systemd[1]: Dependency failed for B.
Jun 30 21:34:59 debug systemd[1]: Job b.service/start failed with result 'dependency'.
Jun 30 21:34:59 debug systemd[1]: Unit a.service entered failed state.
Jun 30 21:34:59 debug systemd[1]: a.service failed.
Jun 30 21:35:04 debug systemd[1]: a.service holdoff time over, scheduling restart.
Jun 30 21:35:04 debug systemd[1]: Starting A...
Jun 30 21:35:04 debug systemd[1]: Started A.
Jun 30 21:35:04 debug sh[1314]: + '[' -f /tmp/success ']'

A は正常に起動しますが、B は障害状態なので再試行しません。

編集する

両方のサービスに以下を追加しました。Aが起動すると、Bは正常に起動しますが、理由を説明できません。

[Install]
WantedBy=multi-user.target

これがAとBの関係に影響を与えるのはなぜですか?

編集2

上記の「修正」はsystemd 220では機能しません。

systemd 219 デバッグログ

systemd219 systemd[1]: Trying to enqueue job b.service/start/replace
systemd219 systemd[1]: Installed new job b.service/start as 3454
systemd219 systemd[1]: Installed new job a.service/start as 3455
systemd219 systemd[1]: Enqueued job b.service/start as 3454
systemd219 systemd[1]: About to execute: /bin/sh -x -c '[ -f /tmp/success ] || (touch oldcoreos
systemd219 systemd[1]: Forked /bin/sh as 1502
systemd219 systemd[1]: a.service changed dead -> start-pre
systemd219 systemd[1]: Starting A...
systemd219 systemd[1502]: Executing: /bin/sh -x -c '[ -f /tmp/success ] || (touch /tmpoldcoreos
systemd219 sh[1502]: + '[' -f /tmp/success ']'
systemd219 sh[1502]: + touch /tmp/success
systemd219 sh[1502]: + sleep 10
systemd219 systemd[1]: a.service start-pre operation timed out. Terminating.
systemd219 systemd[1]: a.service changed start-pre -> final-sigterm
systemd219 systemd[1]: Child 1502 belongs to a.service
systemd219 systemd[1]: a.service: control process exited, code=killed status=15
systemd219 systemd[1]: a.service got final SIGCHLD for state final-sigterm
systemd219 systemd[1]: a.service changed final-sigterm -> failed
systemd219 systemd[1]: Job a.service/start finished, result=failed
systemd219 systemd[1]: Failed to start A.
systemd219 systemd[1]: Job b.service/start finished, result=dependency
systemd219 systemd[1]: Dependency failed for B.
systemd219 systemd[1]: Job b.service/start failed with result 'dependency'.
systemd219 systemd[1]: Unit a.service entered failed state.
systemd219 systemd[1]: a.service failed.
systemd219 systemd[1]: a.service changed failed -> auto-restart
systemd219 systemd[1]: a.service: cgroup is empty
systemd219 systemd[1]: a.service: cgroup is empty
systemd219 systemd[1]: a.service holdoff time over, scheduling restart.
systemd219 systemd[1]: Trying to enqueue job a.service/restart/fail
systemd219 systemd[1]: Installed new job a.service/restart as 3718
systemd219 systemd[1]: Installed new job b.service/restart as 3803
systemd219 systemd[1]: Enqueued job a.service/restart as 3718
systemd219 systemd[1]: a.service scheduled restart job.
systemd219 systemd[1]: Job b.service/restart finished, result=done
systemd219 systemd[1]: Converting job b.service/restart -> b.service/start
systemd219 systemd[1]: a.service changed auto-restart -> dead
systemd219 systemd[1]: Job a.service/restart finished, result=done
systemd219 systemd[1]: Converting job a.service/restart -> a.service/start
systemd219 systemd[1]: About to execute: /bin/sh -x -c '[ -f /tmp/success ] || (touch oldcoreos
systemd219 systemd[1]: Forked /bin/sh as 1558
systemd219 systemd[1]: a.service changed dead -> start-pre
systemd219 systemd[1]: Starting A...
systemd219 systemd[1]: Child 1558 belongs to a.service
systemd219 systemd[1]: a.service: control process exited, code=exited status=0
systemd219 systemd[1]: a.service got final SIGCHLD for state start-pre
systemd219 systemd[1]: About to execute: /bin/true
systemd219 systemd[1]: Forked /bin/true as 1561
systemd219 systemd[1]: a.service changed start-pre -> running
systemd219 systemd[1]: Job a.service/start finished, result=done
systemd219 systemd[1]: Started A.
systemd219 systemd[1]: Child 1561 belongs to a.service
systemd219 systemd[1]: a.service: main process exited, code=exited, status=0/SUCCESS
systemd219 systemd[1]: a.service changed running -> exited
systemd219 systemd[1]: a.service: cgroup is empty
systemd219 systemd[1]: About to execute: /bin/true
systemd219 systemd[1]: Forked /bin/true as 1563
systemd219 systemd[1]: b.service changed dead -> running
systemd219 systemd[1]: Job b.service/start finished, result=done
systemd219 systemd[1]: Started B.
systemd219 systemd[1]: Starting B...
systemd219 systemd[1]: Child 1563 belongs to b.service
systemd219 systemd[1]: b.service: main process exited, code=exited, status=0/SUCCESS
systemd219 systemd[1]: b.service changed running -> exited
systemd219 systemd[1]: b.service: cgroup is empty
systemd219 sh[1558]: + '[' -f /tmp/success ']'

systemd 220 デバッグログ

systemd220 systemd[1]: b.service: Trying to enqueue job b.service/start/replace
systemd220 systemd[1]: a.service: Installed new job a.service/start as 4846
systemd220 systemd[1]: b.service: Installed new job b.service/start as 4761
systemd220 systemd[1]: b.service: Enqueued job b.service/start as 4761
systemd220 systemd[1]: a.service: About to execute: /bin/sh -x -c '[ -f /tmp/success ] || (touch /tmp/success && sleep 10)'
systemd220 systemd[1]: a.service: Forked /bin/sh as 2032
systemd220 systemd[1]: a.service: Changed dead -> start-pre
systemd220 systemd[1]: Starting A...
systemd220 systemd[2032]: a.service: Executing: /bin/sh -x -c '[ -f /tmp/success ] || (touch /tmp/success && sleep 10)'
systemd220 sh[2032]: + '[' -f /tmp/success ']'
systemd220 sh[2032]: + touch /tmp/success
systemd220 sh[2032]: + sleep 10
systemd220 systemd[1]: a.service: Start-pre operation timed out. Terminating.
systemd220 systemd[1]: a.service: Changed start-pre -> final-sigterm
systemd220 systemd[1]: a.service: Child 2032 belongs to a.service
systemd220 systemd[1]: a.service: Control process exited, code=killed status=15
systemd220 systemd[1]: a.service: Got final SIGCHLD for state final-sigterm.
systemd220 systemd[1]: a.service: Changed final-sigterm -> failed
systemd220 systemd[1]: a.service: Job a.service/start finished, result=failed
systemd220 systemd[1]: Failed to start A.
systemd220 systemd[1]: b.service: Job b.service/start finished, result=dependency
systemd220 systemd[1]: Dependency failed for B.
systemd220 systemd[1]: b.service: Job b.service/start failed with result 'dependency'.
systemd220 systemd[1]: a.service: Unit entered failed state.
systemd220 systemd[1]: a.service: Failed with result 'timeout'.
systemd220 systemd[1]: a.service: Changed failed -> auto-restart
systemd220 systemd[1]: a.service: cgroup is empty
systemd220 systemd[1]: a.service: Failed to send unit change signal for a.service: Transport endpoint is not connected
systemd220 systemd[1]: a.service: Service hold-off time over, scheduling restart.
systemd220 systemd[1]: a.service: Trying to enqueue job a.service/restart/fail
systemd220 systemd[1]: a.service: Installed new job a.service/restart as 5190
systemd220 systemd[1]: a.service: Enqueued job a.service/restart as 5190
systemd220 systemd[1]: a.service: Scheduled restart job.
systemd220 systemd[1]: a.service: Changed auto-restart -> dead
systemd220 systemd[1]: a.service: Job a.service/restart finished, result=done
systemd220 systemd[1]: a.service: Converting job a.service/restart -> a.service/start
systemd220 systemd[1]: a.service: About to execute: /bin/sh -x -c '[ -f /tmp/success ] || (touch /tmp/success && sleep 10)'
systemd220 systemd[1]: a.service: Forked /bin/sh as 2132
systemd220 systemd[1]: a.service: Changed dead -> start-pre
systemd220 systemd[1]: Starting A...
systemd220 systemd[1]: a.service: Child 2132 belongs to a.service
systemd220 systemd[1]: a.service: Control process exited, code=exited status=0
systemd220 systemd[1]: a.service: Got final SIGCHLD for state start-pre.
systemd220 systemd[1]: a.service: About to execute: /bin/true
systemd220 systemd[1]: a.service: Forked /bin/true as 2136
systemd220 systemd[1]: a.service: Changed start-pre -> running
systemd220 systemd[1]: a.service: Job a.service/start finished, result=done
systemd220 systemd[1]: Started A.
systemd220 systemd[1]: a.service: Child 2136 belongs to a.service
systemd220 systemd[1]: a.service: Main process exited, code=exited, status=0/SUCCESS
systemd220 systemd[1]: a.service: Changed running -> exited
systemd220 systemd[1]: a.service: cgroup is empty
systemd220 systemd[1]: a.service: cgroup is empty
systemd220 systemd[1]: a.service: cgroup is empty
systemd220 systemd[1]: a.service: cgroup is empty
systemd220 sh[2132]: + '[' -f /tmp/success ']'

答え1

このトピックに関する情報がほとんどないため、他の人がこの問題に直面する場合に備えて、この問題に関する私が見つけた内容を要約しようとしています。

  • Restart=on-failureプロセス障害のみに適用(依存性障害による障害には適用されません)
  • 依存関係が正常に再起動すると、特定の条件下で失敗した依存関係を持つデバイスが再起動されました。 systemd < 220のバグ: http://lists.freedesktop.org/archives/systemd-devel/2015-July/033513.html
  • 起動時に依存関係が失敗する可能性が低く、復元力が重要な場合は、Before/を使用せず、After代わりに依存関係によって生成されたいくつかの成果物を確認してください。

例えば

ExecStartPre=/usr/bin/test -f /some/thing
Restart=on-failure
RestartSec=5s

を使用することもできますsystemctl is-active <dependecy>

非常にハッキーですが、まだ良いオプションが見つかりませんでした。

私の考えでは、依存関係エラーを処理する方法がないのはsystemdの欠陥です。

答え2

これは簡単にスクリプトを書いてcronjobに入れることができるようです。基本的なロジックはこれです

  1. サービスaとb、および依存関係が実行されているか有効な状態であることを確認してください。すべてが正常に動作していることを確認するための最良の方法がわかります。
  2. すべてが正常な場合は何もしないか、すべてが正常であることを記録してください。ロギングの利点は、以前のログエントリを見つけることができることです。
  3. 問題が発生した場合は、サービスを再起動し、サービスと依存関係のヘルスチェックを実行するスクリプトの先頭に戻ります。ジャンプは、サービスを再起動し、依存関係が機能する可能性が高いと確信している場合にのみ発生する必要があります。そうしないと、ループが発生する可能性があります。
  4. cronに後でスクリプトを再実行させます。

スクリプトが設定されると、cronはこれをテストするのに最適な場所です。cronが非効率的である場合、スクリプトは他のサービスの状態を確認できる低レベルのシステムサービスを作成するための良い開始点になります。必要に応じてサービスを再起動します。どのくらいの努力をしたいかによって、結果に基づいて電子メールを送信するようにスクリプトを設定することもできます(もちろん、そのサービスがWebサービスである場合を除く)。

答え3

Afterそして、Beforeサービスが開始される順序を設定すると、サービスファイルに「AとBが起動するには、AがBの前に開始する必要があります」と表示されます。

Requiresこのサービスを開始するには、最初に開始する必要があることを意味します。例では、「Bが起動してAが実行されていない場合はAを起動します」

これを追加すると、WantedBy=multi-user.targetシステムの初期化時にサービスを開始する必要があることをシステムに通知します。multi-user.targetおそらくサービスを追加すると、手動で起動するのではなく、システムがサービスを開始できるようになります。

なぜこれがバージョン220で動作しないのかわかりません。 222を試してみる価値があるでしょう。機会があれば、仮想マシンを掘り下げてサービスを試してみましょう。

答え4

https://github.com/systemd/systemd/issues/1312#issuecomment-1139234399

興味はありませんが、Upholds=コミットに新しいものが導入されますか?0bc488cPR#19322の内容はここで役に立ちますか?

特にb.service構成にWants=a.serviceおよびAfter=a.serviceがあると仮定しますRestart=on-failure。その後、a.service起動時にタイムアウトが発生し、b.service失敗して表示されますb.service/start failed with result 'dependency'。次に、a.service再起動は成功しますが起動b.serviceしません。明らかに、依存関係の失敗はスキーマによるトリガーとは見なされないからですRestart=on-failure

(すでに接続されているStack Exchangeに報告されているものはこれです。質問回答コメントの1つもこの質問に再リンクされます。 )

この長い問題が発生した後、このディレクティブは?として指定され、構成されてUpholds=いる場合は影響を与えるかどうか疑問に思います。これがついにリリースされるとリリースにつながりますか?a.serviceUpholds=b.serviceb.servicea.service

systemdを次にアップグレードできる場合v254返品試してみてください RestartMode=direct:https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html#RestartMode=

関連情報