OnFailure= と Restart= とシステム動作の混同

OnFailure= と Restart= とシステム動作の混同

私は組み込みシステムでsystemd 231を使用しており、システムのハードウェアコンポーネントを監視するサービスを作成しようとしています。私がやりたいことのおおよその説明は次のとおりです。

  1. サービスがfoo.service起動するとアプリケーションが起動しますfoo_app
  2. foo_app継続的に実行されているハードウェアコンポーネントを監視します。
  3. ハードウェア障害が検出されると、foo_appコード1で終了します。これでシステムが再起動します。
  4. 競合が発生した場合は、foo_appsystemdを再起動する必要がありますfoo_app
  5. もしfoo_app どんどん競合が発生した場合、systemdはシステムを再起動する必要があります。

これはサービスとして実装する試みです。

[Unit]
Description=Foo Hardware Monitor

# If the application fails 3 times in 30 seconds, something has gone wrong,
# and the state of the hardware can't be guaranteed. Reboot the system here.
StartLimitBurst=3
StartLimitIntervalSec=30
StartLimitAction=reboot

# StartLimitAction=reboot will reboot the box if the app fails repeatedly,
# but if the app exits voluntarily, the reboot should trigger immediately
OnFailure=systemd-reboot.service

[Service]
ExecStart=/usr/bin/foo_app

# If the app fails from an abnormal condition (e.g. crash), try to
# restart it (within the limits of StartLimit*).
Restart=on-abnormal

ドキュメントから(システムサービスそしてシステムサービスfoo_app)、トリガ方式で終了する場合Restart=on-abnormal(たとえばkillall -9 foo_app)、systemdはstartの代わりに優先Restart=on-abnormal順位を付ける必要があります。OnFailure=systemd-reboot.servicesystemd-reboot.service

しかし、私が見たことはそうではありませんでした。一度殺すと、foo_appシステムはすぐに再起動します。

以下は文書の関連部分です。

OnFailure=

このデバイスが「失敗」状態に入ったときにアクティブになる1つ以上のデバイスをスペースで区切ったリスト。 Restart =を使用するサービスデバイスは、起動制限に達した後にのみエラー状態に入ります。

Restart=

[切る]サービスの再起動には、StartLimitIntervalSec =とStartLimitBurst =で構成されるデバイスの起動速度制限が適用されます。詳細については、systemd.unit(5)を参照してください。再起動されたサービスは、開始制限に達した後にのみ障害状態になります。

文書は明確に見えます。

  • で指定されたサービスは、サービスが ""状態に移行したときにのみ実行するOnFailure必要があります。failed
  • サービスは満たされた後にのみ「」状態に入るべきですfailedStartLimitIntervalSecStartLimitBurst

私が見たことはありません。

これを確認するために、サービスファイルを次のように編集しました。

[Unit]
Description=Foo Hardware Monitor  
  
StartLimitBurst=3
StartLimitIntervalSec=30
StartLimitAction=none

[Service]
ExecStart=/usr/bin/foo_app
Restart=on-abnormal

を削除しOnFailureて設定することで、StartLimitAction=nonesystemdが死にどのように反応するかを確認できましたfoo_app。これはfoo_app私が殺すために繰り返し使用したテストですSIGKILL

[root@device ~]
# systemctl start foo.service
[root@device ~]
# journalctl -f -o cat -u foo.service &
[1] 2107
Started Foo Hardware Monitor.
[root@device ~]
# killall -9 foo_app
foo.service: Main process exited, code=killed, status=9/KILL
foo.service: Unit entered failed state.
foo.service: Failed with result 'signal'
foo.service: Service hold-off time over, scheduling restart.
Stopped foo.
Started foo.

[root@device ~]
# killall -9 foo_app
foo.service: Main process exited, code=killed, status=9/KILL
foo.service: Unit entered failed state.
foo.service: Failed with result 'signal'
foo.service: Service hold-off time over, scheduling restart.
Stopped foo.
Started foo.

[root@device ~]
# killall -9 foo_app
foo.service: Main process exited, code=killed, status=9/KILL
foo.service: Unit entered failed state.
foo.service: Failed with result 'signal'
foo.service: Service hold-off time over, scheduling restart.
Stopped foo.
foo.service: Start request repeated too quickly
Failed to start foo.
foo.service: Unit entered failed state.
foo.service: Failed with result 'start-limit-hit'

これは意味があるか、ほとんどです。foo_app終了すると、systemdはStartLimitBurstヒットするまで再起動して放棄します。を除いて、これは私が望むものですStartLimitAction=reboot

異常にsystemdは、再起動を通過しようとしても終了するたびfoo.service: Unit entered failed state.foo_app印刷しますRestart=on-abnormal。これは、上記の文書の次の内容と直接矛盾するようです。

Restart =を使用するサービスデバイスは、起動制限に達した後にのみエラー状態に入ります。

再起動されたサービスは、開始制限に達した後にのみ障害状態になります。

これらすべてが私を混乱させます。これらのsystemdオプションを誤解しましたか?システムエラーですか?助けてくれてありがとう。

ベストアンサー1

2019/08/12 編集者:therealjumboコメントによると、この問題に対する修正はsystemdv239とマージされてリリースされたため、リリースによって特定のバージョンに固定されていない場合(CentOSを見て)更新して幸せです!

TL;DR - 既知の文書の問題、現在のsystemdプロジェクトに対する未解決の問題

お問い合わせの後、このような内容が報道されたことが確認されました。違いとして認識systemd文書化と実際の動作の間のどこかにあります。私の理解(およびgithubの問題についての私の読書)によると、あなたの期待は文書と一致しているので、狂っているわけではありません。

現在、systemd実行制限に達したかどうかにかかわらず、各起動試行後にステータスが失敗に設定されます。今号では、OPは自転車の乗り方を学ぶことに関する興味深い逸話を書いていますが、ぜひ確認してみることを強くお勧めします。

おすすめ記事