サービスが失敗した場合にクリーンアップを実行するには、 ExecStopPost= を使用できます 、サービスが成功するかどうかにかかわらず実行されます。
ExecStopPost= で実行するコードでは 、 $SERVICE_RESULT のいずれかを使用できます 、 $EXIT_CODE または $EXIT_STATUS 故障状態を判断し、それに応じて対処します。これらの環境変数に関するドキュメントを参照して、どれが適切かを確認してください。
次に、 Restart=on-failure を使用できます systemd が失敗したときにユニットを再起動しようとするようにします。
全部合わせるとこんな感じになります。 run_program と仮定すると ファイルが破損している場合は常にステータス 2 で終了します (上記のドキュメントの他の障害シナリオにこれを適用できることを願っています)。これは機能するはずです:
[Service]
ExecStart=/bin/run_program
ExecStopPost=/bin/sh -c 'if [ "$$EXIT_STATUS" = 2 ]; then rm /file/to/delete; fi'
Restart=on-failure
(注 :二重ドル記号 $$ これをsystemdにエスケープすることなので、シェルは $EXIT_STATUS を認識します そしてその変数にアクセスします。単一のドル記号を使用することもできますが、代わりに systemd がその置換を行い、シェルは [ "2" = 2 ] を表示します。 、これも間違いなく機能します... とにかく、このすべてのロジックをシェルスクリプトに入れ、 ExecStopPost= のフルパスで呼び出すことで、そのほとんどをバイパスできます 、おそらくより良いでしょうし、エラー状態から回復するために実行されたアクションをログに記録するなど、より多くのコマンドをスクリプトに簡単に追加することもできます.)
これにより、特定の状況でこれを正しく構成する方法を理解するための十分なヒントが得られることを願っています!
注意 :おそらく ExecStopPost= を使いたいでしょう OnFailure= の代わりに ここ(私の他の回答を参照)、これはあなたの OnFailure= の理由に対処しようとしています セットアップが機能していません。
OnFailure= の問題 ユニットを開始しないのは、間違ったセクションにあるためかもしれません。[Unit] にある必要があります セクションであり、[Service] ではありません .
代わりにこれを試すことができます:
# software.service
[Unit]
Description=Software
OnFailure=software-fail.service
[Service]
ExecStart=/bin/run_program
そして:
# software-fail.service
[Unit]
Description=Delete corrupt files
[Service]
ExecStart=/bin/rm /file/to/delete
ExecStop=/bin/systemctl --user start software.service
このセットアップで動作させることができます。
ただし、 OnFailure= を使用することに注意してください プログラムが失敗した理由を実際に知ることができず、 ExecStop= で別の開始を連鎖させるため、ここでは理想的ではありません /bin/systemctl start を呼び出して 直接はかなりハックです... ExecStopPost= を使用したソリューション 終了ステータスを見ることは間違いなく優れています。
OnFailure= を定義すると [Service] 内 、systemd (少なくとも Fedora 27 のバージョン 234) は次のように文句を言います:
software.service:6: Unknown lvalue 'OnFailure' in section 'Service'
ログにそれが表示されているかどうかはわかりません... (これは最近の systemd で追加されたのでしょうか?) これはそこで何が起こっているかのヒントになるはずです.