web-dev-qa-db-ja.com

ネットワーキングがシャットダウンする前にサスペンド時にsystemdユニットをトリガーするにはどうすればよいですか?

(ストックDebian別名ストレッチ9なので、通常のsystemd + logind + NetworkManager + GNOMEスタックがあります)

起動/シャットダウンおよび再開/一時停止時に実行するスクリプトのペアがあります。このスクリプトを実行するには、ネットワークが存在している必要があります。私は次のスクリプトでこれを試みました:

[Unit]
Description=Yamaha Reciever power
Requires=network-online.target
After=network-online.target
Before=sleep.target
Conflicts=sleep.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/av-up
ExecStop=/usr/local/bin/av-down
RemainAfterExit=yes

[Install]
WantedBy=graphical.target

これは起動/シャットダウン時に正しく機能しますが、一時停止中にafterが実行され、ネットワークがシャットダウンして失敗します。

これの理由は、systemdで中断がどのように進行するかであると判断しました。

  1. 一時停止はプログラムによって開始されます(例:systemctl suspend)dbus呼び出しをlogindに送信します。
  2. 次に、LoginはPrepareToShutdown dbus信号をリッスンしている人に送信します。
  3. その後、logindはStartUnit dbus呼び出しをsystemdに送信して、suspend.targetユニットを実行します。

NetworkManagerはPrepareToShutdownをリッスンするため、(2)でネットワークを削除し、systemdが(3)で実際にサスペンドを開始したときにユニットがトリガーされます。 NetworkManagerは、logindで「禁止」ロックを保持し、ネットワークをシャットダウンする前に確認します(3)。 (補足:systemdがサスペンド/レジュームの順序を制御するようなものを持っているのはおかしいようですが、logindでこれを覆すことで、これを回避できます)

ネットワーキングがまだ実行されている間にプログラムをサスペンド/レジュームで実行するようにトリガーする正しい方法は何ですか?

NetworkManagerプレダウンスクリプトを使用する必要がありますか?もしそうなら、ネットワークがダウンしたときにトリガーを停止する方法はありますが、サスペンドしていません

以前に中断プロセスにフックする方法はありますか?

NetworkManagerがネットワークをより長く維持する方法はありますか?

注意:これは サスペンド/レジュームについて話しているときにネットワークがダウンする前に起動するSystemdユニットを書き込む方法 とは異なります(---)。

7
David

https://unix.stackexchange.com/a/139664/160746 に触発されて、開始/停止スクリプトを完全なデーモンにアップグレードして、PrepareToShutdownシグナルをリッスンさせました。これは、起動/停止のたびにNetworkManagerと競合しますが、私のシステムでは確実に機能するようです。

https://github.com/davidn/av にコードとsystemdユニットをアップロードしました。

3
David

systemd-suspend のドキュメント、および systemctlのマニュアルページsystemctl suspendによると、suspend.targetがアクティブになります。

systemctl list-dependencies suspend.target --after --allは、suspend.targetsystemctl-suspend.service、次にsleep.targetを呼び出すことを示しています。つまり、systemctl suspendを呼び出すと、default操作の順序は次のようになります。

suspend.target
|-systemd-suspend.service
  |-sleep.target

Before=sleep.targetを配置した場合、your操作の順序は次のようになります。

suspend.target
|-systemd-suspend.service
  |-[custom service]
    |-sleep.target

つまり、サービス実行systemd-suspend.serviceはそのことを実行します。これはおそらくあなたの問題です。


サービスファイルに追加して正しい結果を取得できます。

Before=systemd-suspend.service

systemctl daemon-reloadを呼び出した後は、systemctl list-dependencies suspend.target --after --allを使用して、suspend.targetsystemd-suspend.serviceの間にサービスが表示されることを確認できます。操作の最終的な順序は次のとおりです。

suspend.target
|-[custom service]
  |-systemd-suspend.service
    |-sleep.target
3
Centimane