
여기에는 두 명의 사용자가 연결하도록 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 -w
lsof 커널 대기를 방지합니다. 여기서는 필요하지 않습니다.-n
호스트 이름에 대한 DNS 조회를 방지합니다.-c /^Xvnc$/b
정규식을 사용하여 정확한 명령 이름이 Xvnc인 프로세스를 찾습니다.-a
필터링할 때 OR가 아닌 AND를 사용하도록 lsof에 지시합니다.-iTCP:5900-5999
X 디스플레이 연결에 사용되는 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