
Eu tenho um servidor Xubuntu 14.04 aqui que executa o xrdp para que alguns usuários se conectem a ele.
Agora há um problema: os usuários que acessam este servidor via RDP a partir de thin clients Windows geralmente usam o "X" para fechar a sessão RDP (portanto, desconectar, mas não fazer logout).
Eu sei que existem algumas opções no sesman.ini para lidar com esse tipo de comportamento, mas como diz a página de manual, essas opções são atualmente ignoradas (e têm sido há anos).
As opções que resolveriam meus problemas são:
KillDisconnected
DisconnectedTimeLimit
IdleTimeLimit
Agora preciso hackear algo que lide com sessões desconectadas. Meu primeiro pensamento foi matar todos os usuários remotos que estão desconectados - mas não sei como obter essas informações sobre quais sessões estão desconectadas.
Então... como encontro sessões desconectadas?
Ou: já existe alguma forma preferida de lidar com sessões desconectadas?
Responder1
Aqui está uma maneira de obter uma lista de sessões xrdp desconectadas. Baseia-se no fato de que oxrdpservidor é, no uso normal do gerenciador de sessão X, o único cliente que estabelece uma conexão TCP com oXvncServidor de exibição do sistema X Window. Quando uma sessão xrdp está ativa, o servidor de exibição Xvnc associado possui duas conexões TCP, uma no estado ESTABLISHED e outra no estado LISTEN. Isso se parece com isto usando olsof(1)programa.
$ 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)
Se o usuário da sessão remota a abandonar fechando a conexão RDP (ou, no caso de uma sessão Apache Guacamole RDP, fechando a janela do navegador), será algo assim:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
Xvnc 1625 guest 1u IPv4 252910 0t0 TCP 127.0.0.1:5910 (LISTEN)
Observe que não há conexão ESTABLISHED neste processo desconectado do servidor de exibição Xvnc. Portanto, qualquer processo Xvnc que esteja apenas escutando é uma sessão desconectada.
Aqui está um script de shell (chamado lsdisconnected
) que exibe o PID e o USUÁRIO para cada sessão remota desconectada. Ele usalsof(1)eboquiaberto(1)para implementar a lógica de conexão.
#!/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];
}
}};
'
Esta é uma maneira prática de encontrar sessões desconectadas da área de trabalho remota; funciona imediatamente após a desconexão, sem necessidade de tempo ocioso.
Para quem talvez não esteja familiarizadolsof(1)aqui está uma explicação dos parâmetros da linha de comando neste exemplo.
-b -w
evita esperas do kernel lsof. Eles não são necessários aqui.-n
evita pesquisas de DNS para nomes de host.-c /^Xvnc$/b
procura processos com o nome exato do comando Xvnc, usando um regex.-a
diz ao lsof para usar AND, não OR, ao filtrar.-iTCP:5900-5999
filtra por portas TCP numeradas de 5900 a 5999, aquelas usadas para conexões de exibição X.)
Responder2
Finalmente encontrei uma solução para isso.
Primeiro de tudo, tive que instalar um pequeno programa chamado xprintidle
:
sudo apt-get install xprintidle
Depois disso, escrevi um pequeno script bash que primeiro busca todos os displays usados pelo Xvnc e xrdp e depois verifica essas sessões de display se elas estiveram inativas por mais de alguns minutos:
#!/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"
Responder3
Post antigo, mas tenho o mesmo problema: os parâmetros KillDisconnected/DisconnectedTimeLimit/IdleTimeLimit em sesman.ini estão inativos com Xvnc.
Uma solução simples é adicionar estes parâmetros ao sesman.ini no parágrafo [Xvnc]:
paramX=-MaxDisconnectionTime
paramX=3600
(com X depende de quantos parâmetros já estão definidos)
Com isso, as sessões desconectadas são encerradas automaticamente após 1 hora.
Responder4
Obrigado pelo lsof
-fu! A detecção de sessões 'mortas' Xvnc
tem sido um problema antigo com o Xrdp
. Incorporei o código de O. Jones em um script de shell que pode ser carregado na inicialização e executado na tela para limpar Xvnc
processos mortos deixados para trás quando um usuário fecha sua janela RDP ou a conexão cai por qualquer motivo. Nunca encontrei uma maneira de Xrdp
lidar com isso, então esse lsof
código é perfeito.
#!/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