Debian + Xfce4 でログイン中の GUI セッションを制御する

DebianXfce4 を普段は物理マシンで使い、必要なときだけ別のマシンから xrdp でリモートデスクトップ接続したい、という運用は合理的である。しかし現実には「ローカルで GUI にログイン中のとき、別環境から xrdp で接続すると認証は成功するのにログイン完了しない」「黒画面で止まる」「ログイン画面に戻される」といった症状が出ることがある。

このとき重要なのは、原因が単純なパスワード不一致やネットワーク不調ではなく、xrdp が一般に採るセッション設計と、Linux のログインセッション管理およびデスクトップ環境の初期化が噛み合わないことで発生し得る、という構造である。

ここでは、まず「なぜ起きるのか」を仕組みから丁寧に説明し、そのうえで「既存のローカル GUI セッションを SSH 経由で安全にログアウトさせて衝突を解消する」方法をまとめる。次に、ログアウト以外も含めて「SSH から Xfce4 セッションを制御する」ための設計を整理する。

なお、xrdp と Xfce4 の分離運用や、その狙いについては以前の記事で整理しているので、ここではそこを起点として議論を積み上げる[1]


1. xrdp は「別セッションの GUI 起動」になりやすい

多くの人は「リモートデスクトップ」と聞くと、ローカルで見ている画面をそのまま別端末から閲覧・操作する仕組みを連想する。しかし xrdp は、一般的な構成ではその直感と異なり、RDP 接続が来るたびにサーバ側で新しいログインセッションを作り、その上で X サーバーとデスクトップ環境を起動する。つまり「ローカルの Xfce4 に入る」のではなく「リモート用の別の Xfce4 を起動する」モデルである。これは xrdp 本体と xorgxrdp の設計・実装、そして利用者向けの情報から読み取れる[2][3][4]

このモデルでは、同一ユーザーがすでにローカルで GUI ログインしていても、理屈の上では別の GUI セッションを追加で起動できる。しかし「理屈の上では可能」と「実際に壊れず運用できる」は別であり、特に同一ユーザーの二重 GUI セッションは、環境依存の前提に引っ掛かりやすい。ユーザー視点の症状は単純で、「ログインできない」「黒画面」「ループ」だが、裏側では次のような段階のどこかで失敗している可能性が高い。

段階 裏側で起きていること 失敗するとどう見えるか なぜローカルログイン中だと起きやすいか
認証後のセッション生成 PAM 等で認証後、ログインセッションが作られ、ユーザーの環境が準備される 認証後すぐ戻される 既存セッションとの整合で想定外が出る
X サーバ起動 xrdp が Xorg を起動し、表示先や認可情報を確立する 黒画面で止まる、セッションが落ちる DISPLAY や権限、ソケット、cookie の取り扱いが環境に依存する
デスクトップ起動 startwm.sh 等から Xfce セッションが起動し、各種コンポーネントが立ち上がる 一瞬表示されて落ちる、または黒画面 既存の設定や起動スクリプトが「1 回しか起動しない」前提だと壊れる
IPC とサービス連携 DBus セッションや通知、スクリーンロックなどが連携し、ユーザー体験が成立する 画面は出ても操作が壊れる、通知が出ない等 DBus セッションが複数になると、どのバスに話しかけるかを間違えやすい

この構造を理解すると「なぜローカルログイン中に xrdp ログインが失敗し得るか」が見える。xrdp は新しい GUI セッションを立ち上げたいが、同一ユーザーの既存 GUI セッションがすでに存在し、しかも GUI の初期化は Xorg、DBus、セッションマネージャ等を跨いで複雑に連携するため、どこかで衝突条件が発生すると一気に崩れる。既存セッションの再利用・再接続はさらに難度が上がり、議論・試行錯誤が多い領域である[5][6]

ここで重要なのは「原因を完全に潰し込む」ことが常に最適ではない点である。もちろんログを追い、構成を固定し、二重セッションでも動くように詰めることは可能だが、環境差分やアップグレード差分に弱くなり、長期運用のコストが上がりやすい。一方、運用として再現性が高いのは「そもそも衝突条件を作らない」ことであり、具体的には「リモート接続が必要なタイミングでは、ローカルの GUI セッションを一度ログアウトしてから xrdp で入る」という割り切りである。採用したのはこの方針であり、その実装が SSH 経由での安全なログアウトである[1]


2. SSH から「ログイン中の GUI セッション」を安全にログアウトさせる

SSH 経由でローカルの Xfce4 をログアウトさせたい、という要件は「GUI を操作する」よりも「ログインセッションを終了する」に近い。ここで最も堅い手段は、Xfce 固有のコマンドを叩いてログアウトを真似ることではなく、Linux のログインセッション管理に対して「このセッションを終了せよ」と命令することである。systemd-logind は、ローカルの GUI、TTY、SSH などのログイン状態を統一的に管理し、セッション単位でプロセスを束ねて扱う。loginctl はそのフロントエンドであり、terminate-session は対象セッション配下のプロセスをまとめて終了するので、結果として Xfce4 も終了し、ユーザー視点ではログアウトになる。loginctl の仕様と logind の役割は公式ドキュメントおよび manpages にまとまっている[7][8]

2.1 セッションを特定する

まず、現在のログインセッションを一覧する。これにより「どのセッションがローカル GUI なのか」を見分けられる。GUI セッションは多くの場合 seat0 に紐づき、TTY は tty2 などの仮想端末になるが、環境差はある。重要なのは USER が対象ユーザーであることと、リモートで落としたいセッションがどれかを間違えないことである[7]

1
  loginctl

慣れるまでは show-session で詳細を確認してから実行するのが安全である。セッション ID を入れて詳細を表示し、ユーザー名、状態、種類などが想定どおりかを確認する[7]

1
2
3
  loginctl show-session
  <session_id>
  </session_id>

2.2 セッションを終了する

対象セッションが特定できたら terminate-session で終了する。これが「SSH から GUI をログアウトさせる」最小かつ堅い手順である。

1
2
3
  sudo loginctl terminate-session
  <session_id>
  </session_id>

2.3 terminate-user は慎重に使う

ユーザー単位で全セッションを落とす terminate-user もある。これはローカル GUI だけでなく、そのユーザーの tty ログインや他の SSH セッションまで落とす可能性があるため、目的が「ローカル GUI の衝突解消」だけなら通常は使わない。ただし緊急時に「対象ユーザーのログイン状態を一掃する」用途では有効である[7]

1
  sudo loginctl terminate-user username

2.4 まとめ

目的 推奨コマンド 理由 副作用
ローカル GUI だけを落とす terminate-session 影響範囲が最小で再現性が高い 指定セッション以外は残る
ユーザーのログインを一掃する terminate-user 緊急時に確実に止められる SSH 作業中の自分も落ち得る

3. SSH から Xfce4 セッションを「制御する」ための設計図

ログアウトはできたとしても、SSH から「通知を出す」「画面をロックする」「パネルを再起動する」「GUI アプリを起動する」といった操作をしたくなる場面はある。このとき、最初に理解すべきは「セッション境界を扱う操作」と「GUI 内部へ命令を送る操作」は別のレイヤであり、必要な前提が異なるという点である。セッション境界は logind が管理しており、GUI の構成に依存しにくい。GUI 内部操作は X11 と DBus に依存し、対象セッションを誤ると別セッションを操作する危険がある。したがって実務では、まずレイヤ A を標準手順にし、必要な場合のみレイヤ B を用いる、という二段構えで運用するのが安全である[7][9]

3.1 まとめ

レイヤ 対象 主な操作 必要な情報 事故ポイント
A ログインセッション ログアウト、ロック、セッション確認 SESSION ID 誤った SESSION ID を指定すると別セッションを落とす
B GUI セッション内部 通知、ロック、パネル再起動、GUI アプリ起動 DISPLAY、DBUS_SESSION_BUS_ADDRESS、対象ユーザー 環境変数の取り違えで別セッションへ命令が飛ぶ

4. loginctl によるセッション境界の制御

セッション境界の制御は「このログインセッションを終える」「このセッションをロックする」といった操作であり、GUI を直接操作する必要がない。したがって SSH 経由でも安定しやすい。基本は「一覧で特定し、詳細で確認し、実行する」という 3 段階である[7]

4.1 一覧と詳細

1
2
3
4
  loginctl list-sessions
loginctl show-session
  <session_id>
  </session_id>

4.2 ログアウト

1
2
3
  sudo loginctl terminate-session
  <session_id>
  </session_id>

4.3 ロック

lock-session は logind の「ロック要求」を発行する操作である。環境によってはこれでスクリーンロックがかかるが、Xfce のスクリーンセーバー構成や統合状況によって、期待どおりに動かないことがある。その場合はレイヤ B のスクリーンセーバ系コマンドに切り替える[7][10]

1
2
3
  sudo loginctl lock-session
  <session_id>
  </session_id>

5. DISPLAY と DBus を掴んで GUI 内部へ命令を送る

GUI 内部操作は「その GUI セッションの中にいる」ことを前提にしているため、SSH から実行する場合は前提を人工的に満たしてやる必要がある。具体的には、対象セッションの DISPLAY と DBUS_SESSION_BUS_ADDRESS を取得し、その環境で対象ユーザーとしてコマンドを実行する。DBus はデスクトップ環境内のプロセス連携に広く使われるため、ここを外すと「コマンドが動かない」か「別セッションに行く」。DBus の概念は freedesktop.org の解説にある[9]

5.1 まず「対象 GUI セッション」を間違えない

ここが最重要である。特に「ローカル GUI と xrdp の GUI が同時に存在し得る」構成では、xfce4-session が複数起動している可能性がある。その場合、単純に 1 個目の PID を拾うという雑な方法は危険である。まず loginctl で「どのセッションが対象か」を確定し、必要なら show-session の情報を使って、どのプロセス群がそのセッション配下かを意識してから進む[7]

5.2 xfce4-session の環境から DISPLAY と DBus を取得する

実務上もっとも簡単で、かつ成功率が高いのは、対象セッションで動いている xfce4-session プロセスの環境変数から DISPLAY と DBUS_SESSION_BUS_ADDRESS を取り出す方法である。pgrep はプロセス検索の標準ツールであり、manpages に仕様がある[11]

1
2
3
  PID=$(pgrep -u username -x xfce4-session | head -n1)
tr '\0' '\n'
  /proc/"$PID"/environ | grep -E '^(DISPLAY|DBUS_SESSION_BUS_ADDRESS)='

上の取得結果を控え、以降のコマンドに必ず渡す。繰り返しになるが、xfce4-session が複数ある場合は head -n1 をやめ、どの PID が対象セッションかを確定してから環境を拾う。

5.3 対象ユーザー権限でコマンドを実行する

GUI 操作は対象ユーザー権限で走ることが前提になることが多い。そのため sudo -u でユーザーを切り替え、env で DISPLAY と DBus を明示する。sudo の挙動は manpages にある[12]

1
  sudo -u username env DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=... notify-send "Title" "Body"

6. SSH からよくやる操作を「安全な順序」でまとめる

ここまでの概念を、実務でそのまま使える形に落とす。最初に「セッション境界で片付くものは loginctl で片付ける」と決めると、必要以上に DISPLAY/DBus を扱わずに済み、運用が単純になる。

目的 推奨(第一選択) 条件付き(第二選択) 補足
ローカル GUI をログアウト sudo loginctl terminate-session SID sudo -u username env … xfce4-session-logout –logout 前者が最も堅い。後者は GUI 内部経由[7][13]
画面ロック sudo loginctl lock-session SID sudo -u username env … xfce4-screensaver-command –lock / xscreensaver-command -lock ロック統合は環境依存[10][14][15]
通知を出す sudo -u username env … notify-send … なし 通知仕様は freedesktop の規約[16][17]
パネル再起動 sudo -u username env … xfce4-panel -r なし Xfce docs に記載[18]
GUI アプリを起動 sudo -u username env … なし DISPLAY/DBus が合っていないと失敗する

xfce4-session-logout の仕様は Debian manpages にある[13]

1
  sudo -u username env DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=... xfce4-session-logout --logout

xfce4-screensaver と xscreensaver は別実装である。どちらを採用しているかでロックコマンドが変わるため、運用として「採用しているスクリーンロック実装」を把握しておく。Xfce docs および xscreensaver のマニュアルが一次情報になる[14][15]

1
2
  sudo -u username env DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=... xfce4-screensaver-command --lock
sudo -u username env DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=... xscreensaver-command -lock

7. 事故を防ぎ、再現性を確保する

SSH から GUI セッションを扱うときの事故は、ほぼ「対象の取り違え」と「強制終了の乱用」に集約される。よって運用ルールは複雑にする必要がなく、むしろ固定ワークフローとして短く決めた方が良い。第一に、xrdp 接続前にローカル GUI を落とす必要があるなら、まず loginctl terminate-session を使う。第二に、GUI 内部操作が必要になったら、loginctl で対象セッションを確認した上で、対象セッションの xfce4-session から DISPLAY と DBus を取得して実行する。第三に、xfce4-session が複数ある場合は PID の決め打ちをしない。第四に、kill -9 のような強制終了は最終手段とし、基本はセッション境界で閉じることで整合性を保つ。これが「設定保存」「後片付け」「次のログインの安定」に効く[7][8][12]

チェック 具体的な確認 意図
対象セッションは正しいか loginctl → loginctl show-session 誤操作を防ぐ
ログアウトは loginctl を優先したか terminate-session を第一選択に固定 GUI 構成差に依存しない手順にする
GUI 操作は DISPLAY/DBus を取得したか /proc//environ から取得 別セッションへ命令が飛ぶのを防ぐ
複数 xfce4-session を想定したか PID を確定してから実行 ローカルと xrdp の取り違えを防ぐ

8. xrdp の失敗と SSH 制御を一つの筋で理解する

ローカルで Xfce4 にログイン中のときに xrdp ログインが成立しない現象は、xrdp が一般に「ローカル画面の共有」ではなく「別セッションの GUI 起動」で動く設計であること、そして同一ユーザーの二重 GUI セッションが Xorg、DBus、セッション管理の複合条件で衝突し得ることに由来する[2][3][5]

これを運用で確実に回避する方法として「リモート接続前にローカル GUI セッションを終了する」があり、その実装として SSH から loginctl terminate-session を使うのが最も堅い[7][8]

さらに SSH から通知やロックなど GUI 内部操作を行う場合は、対象セッションの DISPLAY と DBus セッション情報を正しく取得し、対象ユーザー権限で命令を送るという二段構えで整理すると、理解と運用の両方が安定する[9][12]


参考文献

  1. id774, macOS から Debian へのリモートデスクトップ接続 (2025-09-09). https://blog.id774.net/entry/2025/09/09/2999/
  2. neutrinolabs/xrdp. https://github.com/neutrinolabs/xrdp
  3. neutrinolabs/xorgxrdp. https://github.com/neutrinolabs/xorgxrdp
  4. Debian Packages: xrdp. https://packages.debian.org/stable/xrdp
  5. xrdp Wiki. https://github.com/neutrinolabs/xrdp/wiki
  6. c-nergy.be: xrdp と再接続・セッションの考え方. https://c-nergy.be/blog/?p=4471
  7. loginctl(1) (man7). https://man7.org/linux/man-pages/man1/loginctl.1.html
  8. systemd-logind.service (systemd upstream docs). https://www.freedesktop.org/software/systemd/man/latest/systemd-logind.service.html
  9. D-Bus(freedesktop.org). https://www.freedesktop.org/wiki/Software/dbus/
  10. logind.conf(5) (Debian manpages). https://manpages.debian.org/testing/systemd/logind.conf.5.en.html
  11. pgrep(1) (Debian manpages). https://manpages.debian.org/stable/procps/pgrep.1.en.html
  12. sudo(8) (Debian manpages). https://manpages.debian.org/stable/sudo/sudo.8.en.html
  13. xfce4-session-logout(1) (Debian manpages). https://manpages.debian.org/testing/xfce4-session/xfce4-session-logout.1.en.html
  14. xfce4-screensaver (Xfce docs). https://docs.xfce.org/apps/xfce4-screensaver/start
  15. xscreensaver-command(1) (jwz.org). https://www.jwz.org/xscreensaver/man1.html
  16. Desktop Notifications Specification (freedesktop.org). https://specifications.freedesktop.org/notification-spec/latest/
  17. notify-send(1) (Debian manpages). https://manpages.debian.org/stable/libnotify-bin/notify-send.1.en.html
  18. xfce4-panel (Xfce docs). https://docs.xfce.org/xfce/xfce4-panel/start
  19. Debian Wiki: Xorg. https://wiki.debian.org/Xorg
  20. logind.conf (systemd upstream docs). https://www.freedesktop.org/software/systemd/man/latest/logind.conf.html