シャットダウン時に systemd ユーザースコープの強制終了を回避する

シャットダウン時に systemd ユーザースコープの強制終了を回避する

私は、LXC コンテナ マネージャーとして機能する Debian Bookworm マシンを作成します。systemd ユーザー スコープを作成する lxc-unpriv-start コマンドで開始された、権限のない LXC コンテナを使用します。サーバーの起動時にコンテナを開始し、サービスの停止時にクリーン シャットダウンを実行するサービスを作成します。すべてのコンテナのシャットダウンには 2 ~ 3 分かかることがあります。メイン サービスを手動で停止すると、すべて正常に動作します。問題は、サーバーをシャットダウンするときに発生します。サービスはコンテナの終了を正しく待機しますが、その間に systemd-logind がすべてのユーザー セッションを強制終了し、コンテナも強制終了してしまうためです。

スリープのみのシェルを作成して状況をシミュレートし、それを実行します。

/usr/bin/systemd-run --user --scope -p "Delegate=yes" wait.sh &

シャットダウン時に強制終了されます。この強制終了を回避するにはどうすればよいですか?

答え1

Linger はその問題を解決するはずです。

からhttps://www.freedesktop.org/software/systemd/man/loginctl.html

1 人以上のユーザーに対してユーザーの残留を有効/無効にします。特定のユーザーに対して有効にすると、起動時にそのユーザーに対してユーザー マネージャーが生成され、ログアウト後も保持されます。これにより、ログインしていないユーザーが長時間実行されるサービスを実行できるようになります。引数として 1 つ以上のユーザー名または数値 UID を取ります。引数を指定しない場合は、呼び出し元のセッションのユーザーに対して残留を有効/無効にします。

loginctl enable-linger <username>

ユーザー セッションの linger を有効にすると、ログアウト後やシステムのシャットダウン中でもコンテナーの実行を継続できます。これにより、systemd-logind がユーザー セッションと関連コンテナーを強制終了することがなくなり、正常にシャットダウンできるようになります。

答え2

コンテナ停止コマンドが「ブロック」すると仮定すると (つまり、コンテナが停止した後に終了すると仮定すると)、おそらく、シェルから直接ではなく、systemd ユーザー サービスを使用してコンテナ開始コマンドを実行できます。複数のコンテナを開始する必要がある場合は、サービス テンプレートを に記述できます$HOME/.config/systemd/user/。サービス テンプレートのファイル名の@前には が必要です.service(例: [email protected])。

ここに例を挙げます:

[Unit]
PartOf=%i.scope
After=%i.scope

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/systemd-run --user --scope -u %i sh -c 'sleep 1d &'
ExecStop=/usr/bin/sleep 1m

ご覧のとおり、スコープ名は生成されたものではなく、「既知」である必要があります。

テンプレートを使用すると、たとえば でコンテナを起動できます。これで、対応するスコープが、その「エージェント」サービスが停止するまで (つまり、コマンドが終了するまで)systemctl --user start test@container-a残っていることがわかります。ExecStop=

systemctl --user daemon-reloadサービス (テンプレート) ファイルに変更を加えた場合は必ず実行する必要がある場合があります。

PS 当然ですが、コンテナ開始/停止コマンドにコンテナ固有の追加の引数 (スコープ名と同じ文字列ではないもの) を渡す必要がある場合は、テンプレートを使用する代わりに、複数のサービス ファイルを作成する必要があるでしょう。

関連情報