我这里有一个 Xubuntu 14.04 服务器,它运行 xrdp,以便让几个用户连接到它。
现在有一个问题:通过 RDP 从 Windows 瘦客户端访问此服务器的用户经常使用“X”关闭 RDP 会话(因此断开连接但不注销)。
我知道 sesman.ini 中有一些选项可以处理这种行为,但正如手册页所说,这些选项目前被忽略了(并且已经忽略了好几年)。
可以解决我的问题的选项是:
KillDisconnected
DisconnectedTimeLimit
IdleTimeLimit
现在我需要破解一些处理断开连接的会话的东西。我的第一个想法是杀死所有断开连接的远程用户 - 但我不知道如何获取哪些会话已断开的信息。
那么...我如何找到断开连接的会话?
或者:是否有任何首选方法来处理断开连接的会话?
答案1
以下是获取已断开连接的 xrdp 会话列表的方法。它依赖于偏磷酸钠在正常的 X 会话管理器使用中,服务器是唯一与虚拟主机X Window System 显示服务器。当 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 显示服务器进程上没有已建立的连接。因此,任何仅处于监听状态的 Xvnc 进程都是断开连接的会话。
以下是一个 shell 脚本(名为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
告诉 lsof 在过滤时使用 AND,而不是 OR。-iTCP:5900-5999
按 TCP 端口号 5900 - 5999 进行过滤,这些端口用于 X 显示连接。
答案2
我终于找到了解决办法。
首先,我必须安装一个名为的小程序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 -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 的代码合并到一个 shell 脚本中,该脚本可以在启动时加载并从屏幕运行,以清理用户关闭 RDP 窗口或连接因任何原因断开时留下的死进程。我从未找到处理此问题的Xvnc
方法,所以这个代码很完美。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