Dada una ID de ventana X11, ¿hay alguna forma de encontrar la ID del proceso que la creó?
Por supuesto, esto no siempre es posible, por ejemplo, si la ventana vino a través de una conexión TCP. Para ese caso, me gustaría la IP y el puerto asociados con el extremo remoto.
La pregunta se hizo antes en Stack Overflow, y un método propuesto fue usar el _NET_WM_PID
propiedad. Pero eso lo establece la aplicación. ¿Hay alguna forma de hacerlo si la aplicación no funciona bien?
Respuesta aceptada:
A menos que su servidor X admita XResQueryClientIds
de la extensión X-Resource v1.2 No sé fácil forma de confiable ID de proceso de solicitud. Sin embargo, hay otras formas.
Si solo tiene una ventana frente a usted y aún no conoce su ID, es fácil averiguarlo. Simplemente abra una terminal al lado de la ventana en cuestión, ejecute xwininfo
allí y haga clic en esa ventana. xwininfo
le mostrará la identificación de la ventana.
Entonces, supongamos que conoce una identificación de ventana, p. 0x1600045, y quiero saber cuál es el proceso que lo posee.
La forma más fácil de verificar a quién pertenece esa ventana es ejecutar XKillClient, es decir:
xkill -id 0x1600045
y ver qué proceso acaba de morir. ¡Pero solo si no te importa matarlo, por supuesto!
Otra forma fácil pero poco confiable es verificar su _NET_WM_PID
y WM_CLIENT_MACHINE
propiedades:
xprop -id 0x1600045
Eso es lo que hacen las herramientas como xlsclients
y xrestop
hacer.
Desafortunadamente, esta información puede ser incorrecta no solo porque el proceso fue malo y los cambió, sino también porque tenía errores. Por ejemplo, después de un bloqueo/reinicio de Firefox, he visto ventanas huérfanas (supongo que del complemento flash) con _NET_WM_PID
apuntando a un proceso, que murió hace mucho tiempo.
La forma alternativa es correr
xwininfo -root -tree
y verifique las propiedades de los padres de la ventana en cuestión. Eso también puede darte algunas pistas sobre los orígenes de las ventanas.
¡Pero! Si bien es posible que no encuentre qué proceso ha creado esa ventana, todavía hay una manera de encontrar desde dónde se ha conectado ese proceso al servidor X. Y de esa manera es para los verdaderos piratas informáticos. 🙂
El ID de ventana 0x1600045 que conoce con los bits inferiores puestos a cero (es decir, 0x1600000) es una "base de clientes". Y todos los ID de recursos asignados para ese cliente están "basados" en él (0x1600001, 0x1600002, 0x1600003, etc.). X-server almacena información sobre sus clientes en la matriz clients[], y para cada cliente su “base” se almacena en la variable clients[i]->clientAsMask. Para encontrar el socket X, correspondiente a ese cliente, debe conectarse al servidor X con gdb
, camine sobre la matriz de clientes [], encuentre el cliente con ese clientAsMask
e imprima su descriptor de socket, almacenado en ((OsCommPtr)(clients[i]->osPrivate))->fd.
Puede haber muchos clientes X conectados, así que para no verificarlos todos manualmente, usemos una función gdb:
define findclient
set $ii = 0
while ($ii < currentMaxClients)
if (clients[$ii] != 0 && clients[$ii]->clientAsMask == $arg0 && clients[$ii]->osPrivate != 0)
print ((OsCommPtr)(clients[$ii]->osPrivate))->fd
end
set $ii = $ii + 1
end
end
Cuando encuentre el enchufe, puede verificar quién está conectado a él y finalmente encontrar el proceso.
Relacionado:¿Cómo descargar una aplicación de la tienda de Windows 10 para descargarla?
ADVERTENCIA :NO adjunte gdb al servidor X desde DENTRO del servidor X. gdb suspende el proceso al que se adjunta, por lo que si se conecta desde dentro de X-session, congelará su servidor X y no podrá interactuar con gdb. Debe cambiar a la terminal de texto (Ctrl+Alt+F2
) o conéctese a su máquina a través de ssh.
Ejemplo:
-
Encuentre el PID de su servidor X:
$ ps ax | grep X 1237 tty1 Ssl+ 11:36 /usr/bin/X :0 vt1 -nr -nolisten tcp -auth /var/run/kdm/A:0-h6syCa
-
La identificación de la ventana es 0x1600045, por lo que la base de clientes es 0x1600000. Conéctese al servidor X y busque el descriptor de socket del cliente para esa base de clientes. Necesitará información de depuración
instalada para X-server (paquete -debuginfo para distribuciones rpm o paquete -dbg para deb).$ sudo gdb (gdb) define findclient Type commands for definition of "findclient". End with a line saying just "end". > set $ii = 0 > while ($ii < currentMaxClients) > if (clients[$ii] != 0 && clients[$ii]->clientAsMask == $arg0 && clients[$ii]->osPrivate != 0) > print ((OsCommPtr)(clients[$ii]->osPrivate))->fd > end > set $ii = $ii + 1 > end > end (gdb) attach 1237 (gdb) findclient 0x1600000 $1 = 31 (gdb) detach (gdb) quit
-
Ahora sabe que el cliente está conectado a un servidor socket 31. Use
lsof
para encontrar cuál es ese socket:$ sudo lsof -n | grep 1237 | grep 31 X 1237 root 31u unix 0xffff810008339340 8512422 socket
(aquí "X" es el nombre del proceso, "1237" es su pid, "root" es el usuario desde el que se ejecuta, "31u" es un descriptor de socket)
Allí puede ver que el cliente está conectado a través de TCP, luego puede ir a la máquina desde la que está conectado y verificar
netstat -nap
allí para encontrar el proceso. Pero lo más probable es que vea un socket de Unix allí, como se muestra arriba, lo que significa que es un cliente local. -
Para encontrar un par para ese socket Unix, puede usar la técnica de MvG (también necesitará información de depuración para su kernel instalado):
$ sudo gdb -c /proc/kcore (gdb) print ((struct unix_sock*)0xffff810008339340)->peer $1 = (struct sock *) 0xffff810008339600 (gdb) quit
-
Ahora que conoce el socket del cliente, use
lsof
para encontrar el PID que lo contiene:$ sudo lsof -n | grep 0xffff810008339600 firefox 7725 username 146u unix 0xffff810008339600 8512421 socket
Eso es todo. El proceso que mantiene esa ventana es "Firefox" con ID de proceso 7725
Edición de 2017 :Hay más opciones ahora como se ve en ¿Quién tiene el otro extremo de este par de sockets de Unix?. Con Linux 3.3 o superior y con lsof
4.89 o superior, puede reemplazar los puntos 3 a 5 anteriores con:
lsof +E -a -p 1237 -d 31
para averiguar quién está en el otro extremo del socket en el fd 31 del proceso del servidor X con ID 1237.