연결이 끊긴 xrdp 세션을 찾는 방법은 무엇입니까?

연결이 끊긴 xrdp 세션을 찾는 방법은 무엇입니까?

여기에는 두 명의 사용자가 연결하도록 xrdp를 실행하는 Xubuntu 14.04 서버가 있습니다.
이제 한 가지 문제가 있습니다. Windows 씬 클라이언트에서 RDP를 통해 이 서버에 액세스하는 사용자는 종종 "X"를 사용하여 RDP 세션을 닫습니다(따라서 연결 해제는 되지만 로그아웃은 아님).

sesman.ini에 이러한 종류의 동작을 처리할 수 있는 몇 가지 옵션이 있다는 것을 알고 있지만 맨페이지에 나와 있듯이 해당 옵션은 현재 무시되고 있습니다(몇 년 동안 지속되어 왔습니다).
내 문제를 해결하는 옵션은 다음과 같습니다.
KillDisconnected
DisconnectedTimeLimit
IdleTimeLimit

이제 연결이 끊긴 세션을 처리하는 무언가를 해킹해야 합니다. 내 첫 번째 생각은 연결이 끊어진 모든 원격 사용자를 죽이는 것이었지만 연결이 끊어진 세션에 대한 정보를 얻는 방법을 모르겠습니다.

그렇다면... 연결이 끊긴 세션을 어떻게 찾을 수 있나요?
아니면 연결이 끊긴 세션을 처리하는 데 선호되는 방법이 이미 있습니까?

답변1

연결이 끊긴 xrdp 세션 목록을 얻는 방법은 다음과 같습니다. 이는 다음과 같은 사실에 의존합니다.xrdp서버는 일반적인 X 세션 관리자 사용에서 TCP 연결을 설정하는 유일한 클라이언트입니다.XvncX 윈도우 시스템 디스플레이 서버. xrdp 세션이 활성화되면 연결된 Xvnc 디스플레이 서버에는 두 개의 TCP 연결이 있습니다. 하나는 ESTABLISHED 상태이고 다른 하나는 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 디스플레이 연결에 사용되는 TCP 포트 번호 5900 - 5999로 필터링합니다.)

답변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에서 비활성화됩니다.

간단한 해결책은 [Xvnc] 단락의 sesman.ini에 다음 매개변수를 추가하는 것입니다.

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

관련 정보