A menos que su servidor X sea compatible XResQueryClientIds
con la extensión X-Resource v1.2, no conozco una manera fácil de solicitar de manera confiable la identificación del proceso. Sin embargo, hay otras formas.
Si solo tiene una ventana frente a usted y aún no conoce su ID, es fácil descubrirlo. Simplemente abra una terminal al lado de la ventana en cuestión, ejecute xwininfo
allí y haga clic en esa ventana. xwininfo
le mostrará el id de la ventana.
Así que supongamos que conoce un id de ventana, por ejemplo, 0x1600045, y desea encontrar 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 para ello, 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 sus propiedades _NET_WM_PID
y WM_CLIENT_MACHINE
propiedades:
xprop -id 0x1600045
Eso es lo que les gusta xlsclients
y xrestop
hacen las herramientas .
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 (desde el complemento flash, supongo) que _NET_WM_PID
apuntan 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 darle 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 hackers reales. :)
El identificador de ventana 0x1600045 que conoce con bits más bajos 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 de clientes [], y para cada cliente su "base" se almacena en la variable clientes [i] -> clientAsMask. Para encontrar el socket X, que corresponde a ese cliente, debe conectarse al servidor X con gdb
, recorrer la matriz de clientes [], encontrar el cliente con eso clientAsMask
e imprimir su descriptor de socket, almacenado en ((OsCommPtr) (clients [i] - > osPrivate)) -> fd.
Puede haber muchos clientes X conectados, por lo 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 zócalo, puede verificar quién está conectado a él y finalmente encontrar el proceso.
ADVERTENCIA : NO conecte gdb al servidor X dentro del servidor X. gdb suspende el proceso al que se adjunta, por lo que si lo adjunta desde dentro de X-session, congelará su servidor X y no podrá interactuar con gdb. Debe cambiar a terminal de texto ( Ctrl+Alt+F2
) o conectarse 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
El ID de la ventana es 0x1600045, por lo que la base de clientes es 0x1600000. Adjunte al servidor X y busque el descriptor de socket del cliente para esa base de clientes. Necesitará la 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 socket de servidor 31. Use lsof
para encontrar qué 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 está ejecutando, "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 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 núcleo 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. El proceso que mantiene esa ventana es "firefox" con process-id 7725
Edición de 2017 : ahora hay más opciones, como se ve en ¿Quién tiene el otro extremo de este par de socket 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 fd 31 del proceso del servidor X con ID 1237.