
Ich habe hier einen Xubuntu 14.04-Server, auf dem xrdp läuft, damit sich mehrere Benutzer damit verbinden können.
Jetzt gibt es ein Problem: Benutzer, die über RDP von Windows-Thin-Clients auf diesen Server zugreifen, verwenden häufig das „X“, um die RDP-Sitzung zu schließen (also die Verbindung zu trennen, sich aber nicht abzumelden).
Ich weiß, dass es in sesman.ini einige Optionen gibt, um mit diesem Verhalten umzugehen, aber wie die Manpage sagt, werden diese Optionen derzeit (und schon seit Jahren) ignoriert.
Die Optionen, die meine Probleme lösen würden, sind:
KillDisconnected
DisconnectedTimeLimit
IdleTimeLimit
Jetzt muss ich etwas hacken, das mit getrennten Sitzungen umgeht. Mein erster Gedanke war, einfach alle Remote-Benutzer zu beenden, deren Verbindung getrennt ist – aber ich weiß nicht, wie ich an die Informationen komme, welche Sitzungen getrennt sind.
Also... wie finde ich getrennte Sitzungen?
Oder: Gibt es bereits eine bevorzugte Methode zum Umgang mit getrennten Sitzungen?
Antwort1
Hier ist eine Möglichkeit, eine Liste der getrennten xrdp-Sitzungen zu erhalten. Sie basiert auf der Tatsache, dass diexrdpDer Server ist bei normaler Verwendung des X-Session-Managers der einzige Client, der eine TCP-Verbindung zumXvncX Window System-Anzeigeserver. Wenn eine xrdp-Sitzung aktiv ist, hat der zugehörige Xvnc-Anzeigeserver zwei TCP-Verbindungen, eine im Status ESTABLISHED und die andere im Status LISTEN. Das sieht ungefähr so aus, wenn man denlsof(1)Programm.
$ 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)
Wenn der Benutzer der Remotesitzung diese durch Schließen der RDP-Verbindung (oder im Fall einer Apache Guacamole RDP-Sitzung durch Schließen des Browserfensters) verlässt, sieht das ungefähr so aus:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
Xvnc 1625 guest 1u IPv4 252910 0t0 TCP 127.0.0.1:5910 (LISTEN)
Beachten Sie, dass bei diesem getrennten Xvnc-Displayserverprozess keine HERGESTELLTE Verbindung besteht. Jeder Xvnc-Prozess, der nur zuhört, ist also eine getrennte Sitzung.
Hier ist ein Shell-Skript (mit dem Namen lsdisconnected
), das die PID und den USER für jede getrennte Remote-Sitzung anzeigt. Es verwendetlsof(1)Undgaffen(1)um die Verbindungslogik zu implementieren.
#!/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];
}
}};
'
Dies ist eine praktische Möglichkeit, getrennte Remote-Desktop-Sitzungen zu finden. Es funktioniert sofort nach der Trennung, ohne dass eine Leerlaufzeit benötigt wird.
Für diejenigen, die vielleicht nicht vertraut sind mitlsof(1)Hier finden Sie eine Erklärung der Befehlszeilenparameter in diesem Beispiel.
-b -w
vermeidet lsof-Kernelwartezeiten. Sie werden hier nicht benötigt.-n
vermeidet DNS-Lookups für Hostnamen.-c /^Xvnc$/b
sucht unter Verwendung eines regulären Ausdrucks nach Prozessen mit dem exakten Befehlsnamen Xvnc.-a
weist lsof an, beim Filtern „AND“ und nicht „OR“ zu verwenden.-iTCP:5900-5999
filtert nach den TCP-Ports mit den Nummern 5900 - 5999, die für X-Display-Verbindungen verwendet werden.)
Antwort2
Ich habe endlich eine Lösung dafür gefunden.
Zuerst musste ich ein kleines Programm namens installieren xprintidle
:
sudo apt-get install xprintidle
Danach habe ich ein kleines Bash-Skript geschrieben, das zuerst alle von Xvnc und xrdp verwendeten Displays abruft und dann diese Displaysitzungen überprüft, wenn sie länger als einige Minuten inaktiv waren:
#!/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"
Antwort3
Alter Beitrag, aber ich habe dasselbe Problem: Die Parameter KillDisconnected/DisconnectedTimeLimit/IdleTimeLimit in sesman.ini sind mit Xvnc inaktiv.
Eine einfache Lösung besteht darin, diese Parameter zum sesman.ini im Absatz [Xvnc] hinzuzufügen:
paramX=-MaxDisconnectionTime
paramX=3600
(bei X abhängig davon wie viele Parameter bereits definiert sind)
Dabei werden getrennte Sitzungen nach 1 Stunde automatisch beendet.
Antwort4
Danke für das lsof
-fu! Das Erkennen von „toten“ Xvnc
Sitzungen ist seit langem ein Problem mit Xrdp
. Ich habe den Code von O. Jones in ein Shell-Skript integriert, das beim Booten geladen und vom Bildschirm aus ausgeführt werden kann, um tote Xvnc
Prozesse zu bereinigen, die zurückbleiben, wenn ein Benutzer sein RDP-Fenster schließt oder die Verbindung aus irgendeinem Grund abbricht. Ich habe nie eine Möglichkeit gefunden, damit Xrdp
umzugehen, also lsof
ist dieser Code perfekt.
#!/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