XDG_RUNTIME_DIR
が機能するには、systemctl --user
が必要です。
Systemdユーザーセッションを実行するようにubuntuサーバー16.04を設定しました。現在、それらを管理しようとすると、Sudo -u $user -i
またはsu - $user
を介してユーザーを変更する場合、環境にXDG_RUNTIME_DIR
が設定されていないため、systemctl --user
が機能しません。ただし、そのユーザーに直接ssh
すると、正しく設定されます。
ドキュメントを正しく理解していれば、ユーザーセッションの作成時にlibpam-systemd
によって設定されているはずです。 XDG_RUNTIME_DIR
が指すディレクトリ(/run/users/$uid
)が存在するため、ユーザースライスは正しく開始されます。 .bash_profile
のようにハードコードするのは躊躇しています。
もちろん、sudoers
のXDG_RUNTIME_DIR
をenv_keep
に追加することもできますが、これはsudoingユーザーの環境を保持するだけであり、私が望むものではありません。 targetユーザーの環境が必要です。
しかし、私が本当に疑問に思っているのは、セッションがssh
またはSudo -i
ではなくsu
で正しく設定されるのはなぜですか?
この問題をFedora 25システムで再現しました。
ソースコードに非常に疑わしい状態が見つかりました。 https://github.com/systemd/systemd/blob/f97b34a/src/login/pam_systemd.c#L439 通常のSudo
を念頭に置いて記述されているように見えますが、 Sudo -u non-root-user
ではありません。
machinectl Shell --uid=non-root-user
はリクエストどおりに機能しました。
systemd-run
は、machinectlのドキュメントで参照されているにもかかわらず、期待どおりに機能していないようです。
現時点でSELinuxを有効にしている場合、一部のmachinectlコマンドは機能せず、これらの特定のコマンドは、setenforce 0
を実行するまで機能しませんでした。しかし、私はmachinectlをSELinuxで希望どおりに機能させるための回避策を試行している最中なので、私の手作業が原因である可能性があります。タイムアウトするmachinectl Shell
。
編集:このコードは このディスカッション の後に導入されたと思います。そして、明らかにsu -
/Sudo -i
を機能させることはできますが、誰も実装していません(まだ)。
しかし、私が本当に疑問に思っているのは、セッションがsshで正しく設定されているのに、suまたはSudo -iでは正しく設定されていないのはなぜですか?
https://github.com/systemd/systemd/issues/7451#issuecomment-346787237
申し訳ありませんが、「su」は、ユーザーIDと他のほとんどのプロセス資格情報を一時的に変更するためのツールです。まったく新しいログインセッションを開くためのツールではありません。新しいログインセッションには、他のセッションから何も継承しない、明確に定義された手付かずの設定がありますが、これは "su" uidの変更には当てはまりません。実行環境のほとんどは、数多くの非自明な形で継承されます方法、たとえば、MACコンテキスト、監査コンテキスト、cgroupコンテキスト、名前空間コンテキスト、スケジューリング、タイマーの粒度、…
完全に新しいセッションが必要な場合は、「machinectl login」や「machinectl Shell」などを使用します。これにより、完全にクリーンな独立したデタッチ環境が得られ、呼び出し先から隠されたプロセスプロパティがリークすることはありません。
ログインしたセッションは、ほとんどが監査セッションの概念に拘束され、監査セッションは「su」の影響を受けません。実際、「封印」されるように定義されています。つまり、プロセスが一度セッションに入ると、常に残ります。つまり、その子も同様です。つまり、新しいセッションを取得する唯一の方法は、PID 1(または類似の何か)からフォークして、セッションの一部になったことがないようにすることです。
または別の言い方をすると、 "su"を介して呼び出したものは "loginctl"で正常に表示されますが、元のセッションの一部であり、最初にログインしました。これは、元のセッションのID(echo $ XDG_SESSION_IDで確認できます)で「loginctl status」を呼び出すことで確認できます。