切断された xrdp セッションを見つけるにはどうすればいいですか?

切断された xrdp セッションを見つけるにはどうすればいいですか?

私は、数人のユーザーが接続できるように xrdp を実行する Xubuntu 14.04 サーバーを所有しています。ここで
問題が 1 つあります。Windows シン クライアントから RDP 経由でこのサーバーにアクセスするユーザーは、RDP セッションを閉じるために「X」を使用することが多いのです (つまり、切断はされますが、ログアウトはされません)。

sesman.ini にそのような動作に対処するためのオプションがいくつかあることは知っていますが、マニュアルページにあるように、それらのオプションは現在無視されています (何年も無視されています)。
私の問題を解決するオプションは次のとおりです:
KillDisconnected
DisconnectedTimeLimit
IdleTimeLimit

今、切断されたセッションを処理する何かをハックする必要があります。最初に考えたのは、切断されたすべてのリモート ユーザーを強制終了することでしたが、どのセッションが切断されたかという情報を取得する方法がわかりません。

では、切断されたセッションを見つけるにはどうすればよいのでしょうか?
または、切断されたセッションを処理するための推奨される方法がすでにあるのでしょうか?

答え1

切断されたxrdpセッションのリストを取得する方法は次のとおりです。xrdp通常のXセッションマネージャの使用では、サーバは、クライアントへのTCP接続を確立する唯一のクライアントです。翻訳X Window Systemディスプレイサーバー。xrdpセッションがアクティブな場合、関連付けられたXvncディスプレイサーバーには2つのTCP接続があり、1つはESTABLISHED状態、もう1つはLISTEN状態です。これは、lsof(1)プログラム。

$ sudo lsof  -b -w -n -c /^Xvnc$/b -a -iTCP:5900-5999 
COMMAND  PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
Xvnc    1625 guest    1u  IPv4 252910      0t0  TCP 127.0.0.1:5910 (LISTEN)
Xvnc    1625 guest    9u  IPv4 261226      0t0  TCP 127.0.0.1:5910->127.0.0.1:35242 (ESTABLISHED)

リモート セッションのユーザーが RDP 接続を閉じて (または、Apache Guacamole RDP セッションの場合は、ブラウザー ウィンドウを閉じて) セッションを放棄すると、次のようになります。

COMMAND  PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
Xvnc    1625 guest    1u  IPv4 252910      0t0  TCP 127.0.0.1:5910 (LISTEN)

この切断された Xvnc ディスプレイ サーバー プロセスには ESTABLISHED 接続がないことに注意してください。したがって、リッスンしているだけの Xvnc プロセスはすべて切断されたセッションです。

lsdisconnected切断されたリモートセッションごとにPIDとUSERを表示するシェルスクリプト( )を以下に示します。lsof(1)そして驚愕(1)接続ロジックを実装します。

#!/bin/bash
sudo lsof -FRgpLT -b -w -n -c /^Xvnc$/b -a -iTCP:5900-5999  |
gawk '
      match($0,/^p([0-9]+)/,       p) {pid = p[1]; pids[pid]=0; } ;
      match($0,/^L([A-Za-z0-9]+)/, p) {user[pid] = p[1]; } ;
      /TST=LISTEN/ {pids[pid] = pids[pid] - 1 ;};
      /TST=ESTABLISHED/{pids[pid] = pids[pid] + 1};
      END {
          for (pid in pids){
              if (pids[pid] < 0) {
                  print pid, user[pid];
              }
          }};
     '

これは、切断されたリモート デスクトップ セッションを見つけるのに便利な方法です。アイドル時間を使用する必要がなく、切断されるとすぐに機能します。

よく知らない人のためにlsof(1)この例のコマンドラインパラメータの説明は次のとおりです。

  • -b -wlsof カーネルの待機を回避します。ここでは必要ありません。
  • -nホスト名の DNS 検索を回避します。
  • -c /^Xvnc$/b正規表現を使用して、正確なコマンド名 Xvnc を持つプロセスを検索します。
  • -aフィルタリング時に OR ではなく AND を使用するように lsof に指示します。
  • -iTCP:5900-5999X ディスプレイ接続に使用される 5900 - 5999 番の TCP ポートでフィルタリングします。

答え2

ついにこの問題の解決策を見つけました。
まず、という小さなプログラムをインストールする必要がありましたxprintidle

sudo apt-get install xprintidle

その後、まず Xvnc と xrdp が使用するすべてのディスプレイを取得し、次にそれらのディスプレイ セッションが一定時間以上アイドル状態になっているかどうかをチェックする小さな bash スクリプトを作成しました。

#!/bin/bash

displays=`ps aux | grep Xvnc | grep -v 'grep\|sed' | sed -r 's|.*(Xvnc :[0-9]*).*|\1|' | cut -d' ' -f 2`
limit=180


date
echo "Checking for inactive sessions!"
while read -r d; do
    export DISPLAY=$d
    idle=`xprintidle`
    idleMins=$(($idle/1000/60))
    if [[ $idleMins -gt $limit ]]; then
        echo "WARN Display $d is logged in for longer than ${limit}min (${idleMins}m)"
    else
        echo "INFO Display $d is still ok (${idleMins}m)"
    fi  
done <<< "$displays"

答え3

古い投稿ですが、私も同じ問題を抱えています。sesman.ini のパラメーター KillDisconnected/DisconnectedTimeLimit/IdleTimeLimit が Xvnc では非アクティブです。

簡単な解決策は、sesman.ini の [Xvnc] 段落に次のパラメータを追加することです。

paramX=-MaxDisconnectionTime
paramX=3600

(X は既に定義されているパラメータの数によって異なります)

これにより、切断されたセッションは 1 時間後に自動的に終了されます。

答え4

-fuをありがとうlsof! 「デッド」Xvncセッションの検出は、 の長年の課題でしたXrdp。私は、O. Jones のコードをシェル スクリプトに組み込みました。このスクリプトは、起動時に読み込まれ、画面から実行して、Xvncユーザーが RDP ウィンドウを閉じたり、何らかの理由で接続が切断されたりしたときに残されたデッド プロセスをクリーンアップできます。 ではこの問題に対処する方法が見つからなかったXrdpため、このlsofコードは完璧です。

#!/bin/bash

#
# this could be launched from rc.local via screen
#   echo '/usr/bin/screen -dmS xrdp_cleanup /root/bin/xrdp_cleanup_discod_sessions' | at now
#
while [ 1 ]; do
   # loop through all listening Xvnc processes and make sure there's an established connection
   for pid in `lsof -b -w -n -c /^Xvnc$/b -a -iTCP:5900-5999 | grep L[I]STEN | awk '{print $2};'`; do

      # new sessions may take a second or two on busy systems. 
      # wait for new LISTEN sessions to be become established. this also acts as a throttle for the loop
      sleep 2

      # get user for the established session
      euser=`lsof -b -w -n -c /^Xvnc$/b -a -iTCP:5900-5999 | grep L[I]STEN | grep "$pid" | awk '{print $3};'`
      esta=`lsof -b -w -n -c /^Xvnc$/b -a -iTCP:5900-5999 | grep E[S]TABLISHED | grep "$pid" | awk '{print $2};'`

      test -z "$euser" && echo "Unable to find user in lsof output!"

      if [ -n "$esta" ]; then
         # regular status update
         echo "user $euser has an established sesson on pid $pid"
      else
         isrunning="yes"

         # make sure the process is killed. keep trying.
         while [ -n "$isrunning" ]; do
            echo "Established session for user $euser is gone. killing pid $pid.."
            kill $pid
            sleep 1
            isrunning=`ps -ef | grep $pid | grep -v grep`
            test -z "$isrunning" && echo "$pid killed OK"
         done
      fi
   done
done

関連情報