
我這裡有一個 Xubuntu 14.04 伺服器,它運行 xrdp 以讓幾個用戶連接到它。
現在有一個問題:從 Windows 瘦客戶端透過 RDP 存取該伺服器的使用者經常使用「X」來關閉 RDP 會話(因此斷開連線但不登出)。
我知道 sesman.ini 中有一些選項可以處理這種行為,但正如線上說明頁所述,這些選項目前被忽略(並且已經存在多年)。
可以解決我的問題的選項是:
KillDisconnected
DisconnectedTimeLimit
IdleTimeLimit
現在我需要破解一些處理斷開連接的會話的東西。我的第一個想法是殺死所有斷開連接的遠端用戶 - 但我不知道如何獲取哪些會話已斷開連接的資訊。
那麼...我要如何找到斷開連線的會話?
或者:是否已經有任何首選方法來處理斷開連接的會話?
答案1
這是獲取斷開連線的 xrdp 會話清單的方法。它依賴於這樣一個事實:XRDP在正常的 X 會話管理器使用中,伺服器是唯一與伺服器建立 TCP 連線的用戶端。XVNCX Window 系統顯示伺服器。當 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 程序都是斷開連線的會話。
這是一個 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
按編號為 5900 - 5999 的 TCP 連接埠進行過濾,這些連接埠用於 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
謝謝你的lsof
-fu!偵測「死」Xvnc
會話一直是Xrdp
.我已將 O. Jones 的程式碼合併到一個 shell 腳本中,該腳本可以在啟動時加載並從螢幕運行,以清理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