私は組み込みシステムでsystemd 231を使用しており、システムのハードウェアコンポーネントを監視するサービスを作成しようとしています。私がやりたいことのおおよその説明は次のとおりです。
- サービスが
foo.service
起動するとアプリケーションが起動しますfoo_app
。 foo_app
継続的に実行されているハードウェアコンポーネントを監視します。- ハードウェア障害が検出されると、
foo_app
コード1で終了します。これでシステムが再起動します。 - 競合が発生した場合は、
foo_app
systemdを再起動する必要がありますfoo_app
。 - もし
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.service
systemd-reboot.service
しかし、私が見たことはそうではありませんでした。一度殺すと、foo_app
システムはすぐに再起動します。
以下は文書の関連部分です。
OnFailure=
このデバイスが「失敗」状態に入ったときにアクティブになる1つ以上のデバイスをスペースで区切ったリスト。 Restart =を使用するサービスデバイスは、起動制限に達した後にのみエラー状態に入ります。
Restart=
[切る]サービスの再起動には、StartLimitIntervalSec =とStartLimitBurst =で構成されるデバイスの起動速度制限が適用されます。詳細については、systemd.unit(5)を参照してください。再起動されたサービスは、開始制限に達した後にのみ障害状態になります。
文書は明確に見えます。
- で指定されたサービスは、サービスが ""状態に移行したときにのみ実行する
OnFailure
必要があります。failed
- サービスは満たされた後にのみ「」状態に入るべきです
failed
。StartLimitIntervalSec
StartLimitBurst
私が見たことはありません。
これを確認するために、サービスファイルを次のように編集しました。
[Unit]
Description=Foo Hardware Monitor
StartLimitBurst=3
StartLimitIntervalSec=30
StartLimitAction=none
[Service]
ExecStart=/usr/bin/foo_app
Restart=on-abnormal
を削除しOnFailure
て設定することで、StartLimitAction=none
systemdが死にどのように反応するかを確認できました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
コメントによると、この問題に対する修正はsystemd
v239とマージされてリリースされたため、リリースによって特定のバージョンに固定されていない場合(CentOSを見て)更新して幸せです!
TL;DR - 既知の文書の問題、現在のsystemd
プロジェクトに対する未解決の問題
お問い合わせの後、このような内容が報道されたことが確認されました。違いとして認識systemd
文書化と実際の動作の間のどこかにあります。私の理解(およびgithubの問題についての私の読書)によると、あなたの期待は文書と一致しているので、狂っているわけではありません。
現在、systemd
実行制限に達したかどうかにかかわらず、各起動試行後にステータスが失敗に設定されます。今号では、OPは自転車の乗り方を学ぶことに関する興味深い逸話を書いていますが、ぜひ確認してみることを強くお勧めします。