完全にシャットダウンされたsystemdサービスを手動でシャットダウンします。

完全にシャットダウンされたsystemdサービスを手動でシャットダウンします。

クラウド仮想マシンで定期的なタスクが実行されています。このマシンタイプは非常に高価であるため、起動時に起動してスクリプトを実行し、マシンをシャットダウンしてコストを節約するsystemdデバイスサービスがあります。これは設計どおりに機能します。

ログインしてservice [] stopコマンドを実行すると、当然システムが即座にシャットダウンされるため、システムを保守することが困難になります。

私はこれが利用可能でなければならないと思いますOnFailureが、何らかの理由でスクリプトが失敗した場合(衝突時にVMが回転するのではなく)、システムがシャットダウンしたいと思います。またはいくつかの用途ExecStop

3つの状況が発生します。

  • プロセスが正しく実行され、シャットダウンされます(例:終了コード0)、システムの電源が切れます。
  • プロセスの競合 (例: 終了コード != 0)、システムの電源切断
  • ユーザーによってサービスが終了/中断されましたか?システムの電源が入っている

簡単な解決策は、開始、ログイン、無効化、再起動(サービスがすでに開始されているため)、メンテナンスタスクの実行、および再起動する前に、サービスに1分の猶予期間を提供することです。ところでこれはちょっと混乱しているようです。参考までに、サービス定義は次のとおりです。

[Unit]
Description="Run job"
After=network.target
StartLimitInterval=200
StartLimitBurst=30
OnFailure=systemd-poweroff.service

[Service]
Type=simple
Restart=on-failure
RestartSec=30
ExecStartPre=/bin/sleep 60
ExecStart=/my/script.sh
ExecStopPost=sudo systemctl poweroff -i
User=foo

[Install]
WantedBy=multi-user.target

セキュリティ認識ではなく、環境設定によりスクリプトが通常のユーザーとして実行されるため、ここではsudoが使用されます(このアカウントには、電源を切るためのパスワードのないsudo権限が特別に付与されます)。

ベストアンサー1

poweroffアクションで実行するのではなく、ExecStopPost別のサービスに移動してください。つまり、「ジョブ実行」サービスを次のようにしてください。

[Unit]
Description="Run job"
After=network.target
Requires=my-poweroff.service
Before=my-poweroff.service

[Service]
Type=oneshot
Restart=on-failure
RestartSec=30
ExecStart=/my/script.sh
User=foo

[Install]
WantedBy=multi-user.target

スクリプトが完了するまでサービスが「起動」されないため、Type=oneshot代わりに使用しています。を使用して/dependentを介して停電をトリガーすると、この操作と終了操作が開始されるType=simpleため、これは重要です。Requires=Before=Type=simple同時に。使用は、Type=oneshotサービスが終了するまでシャットダウンジョブが実行されないことを意味します。

次に、my-poweroff.service次のようになります。

[Unit]
ConditionPathExists=!/run/nopoweroff

[Service]
Type=simple
ExecStart=/usr/bin/systemctl poweroff -i

これで、「ジョブの実行」サービスが完了するまでpoweroffブロックします。touch /run/nopoweroff

おすすめ記事