如何find断开xrdp会话?

我有一台运行xrdp的Xubuntu 14.04服务器,有几个用户连接到它。
现在有一个问题:从Windows瘦客户端通过RDP访问此服务器的用户通常使用“X”closuresRDP会话(因此断开连接但不注销)。

我知道在sesman.ini中有一些选项可以处理这种行为,但正如手册中所说,这些选项目前被忽略(并且已经存在多年)。
解决我的问题的选项是:
KillDisconnected
DisconnectedTimeLimit
IdleTimeLimit

现在我需要破解一些处理断开连接的会话。 我的第一个想法是杀死所有断开连接的远程用户 – 但是我不知道如何获得那些会话断开连接的信息。

所以…我如何find断开的会话?
或者:是否有任何首选的方法来处理断开连接的会话?

我终于find了解决办法。
首先,我不得不安装一个名为xprintidle的小程序:

 sudo apt-get install xprintidle 

之后,我写了一个小的bash脚本,首先获取Xvnc和xrdp使用的所有显示,然后检查显示会话是否空闲了超过几分钟:

 #!/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 -rd; 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" 

这是一种获取断开的xrdp会话列表的方法。 它依赖于xrdp服务器在正常的X会话pipe理器使用情况下是唯一build立到Xvnc X Window系统显示服务器的TCP连接的客户端。 当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) 

如果远程会话的用户通过closuresRDP连接(或者在Apache Guacamole RDP会话的情况下closures浏览器窗口)来放弃它,则看起来像这样:

 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进程都是断开的会话。

这是一个shell脚本(名为lsdisconnected ),显示每个断开的远程会话的PID和USER。 它使用lsof(1)gawk(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查找进程,使用正则expression式。
  • -a告诉lsof在过滤时使用AND而不是OR。
  • -iTCP:5900-5999通过编号为-iTCP:5900-5999的TCP端口进行过滤,用于X显示连接。)

感谢lsof -fu! 检测“死亡” Xvnc会话一直是Xrdp长期存在的问题。 我将O. Jones的代码合并到一个shell脚本中,可以在启动时加载并从屏幕上运行,以清理用户closuresRDP窗口时遗留的死亡Xvnc进程,或者连接因为某种原因而丢失。 我从来没有find与Xrdp的方式来处理这个问题,所以这个代码是完美的。

 #!/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