How to find disconnected xrdp sessions?
Here is a way to obtain a list of disconnected xrdp sessions. It relies on the fact that the xrdp server is, in normal X session manager usage, the only client that establishes a TCP connection to the Xvnc X Window System display server. When an xrdp session is active, the associated Xvnc display server has two TCP connections, one in the ESTABLISHED state, and the other in the LISTEN state. That looks something like this using the lsof(1) program.
$ 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)
If the user of the remote session abandons it by closing the RDP connection (or, in the case of an Apache Guacamole RDP session, by closing the browser window) it looks something like this:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
Xvnc 1625 guest 1u IPv4 252910 0t0 TCP 127.0.0.1:5910 (LISTEN)
Notice there's no ESTABLISHED connection on this disconnected Xvnc display server process. So, any Xvnc process that's only listening is a disconnected session.
Here's a shell script (named lsdisconnected
) that displays the PID and USER for each disconnected remote session. It uses lsof(1) and gawk(1) to implement the connection logic.
#!/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];
}
}};
'
This is a handy way to find disconnected remote desktop sessions; it works immediately upon disconnection, without needing to use an idle time.
For those who may not be familiar with lsof(1) here's an explanation of the command line parameters in this example.
-
-b -w
avoids lsof kernel waits. They're not needed here. -
-n
avoids DNS lookups for hostnames. -
-c /^Xvnc$/b
looks for processes with the exact command name Xvnc, using a regex. -
-a
tells lsof to use AND, not OR, when filtering. -
-iTCP:5900-5999
filters by TCP ports numbered 5900 - 5999, the ones used for X display connections.)
I finally found a solution to this.
First of all, I had to install a small program called xprintidle
:
sudo apt-get install xprintidle
After that I wrote a small bash script that first fetches all displayes used by Xvnc and xrdp and then checks those display sessions if they've been idle for more than a number of minutes:
#!/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"