¿Qué proceso creó esta ventana X11?

75

Dada una ID de ventana X11, ¿hay alguna manera 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 sobre Stack Overflow , y un método propuesto era usar la _NET_WM_PIDpropiedad. Pero eso lo establece la aplicación. ¿Hay alguna manera de hacerlo si la aplicación no funciona bien?

Gilles 'SO- deja de ser malvado'
fuente
Relacionado: PID de ID / nombre de la ventana
Gilles 'SO- deja de ser malvado'

Respuestas:

60

A menos que su servidor X sea compatible XResQueryClientIdscon 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 xwininfoallí y haga clic en esa ventana. xwininfole 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_PIDy WM_CLIENT_MACHINEpropiedades:

xprop -id 0x1600045

Eso es lo que les gusta xlsclientsy xrestophacen 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_PIDapuntan 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 clientAsMaske 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:

  1. 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
    
  2. 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
    
  3. Ahora sabe que el cliente está conectado a un socket de servidor 31. Use lsofpara 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 -napallí 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.

  4. 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
    
  5. Ahora que conoce el socket del cliente, use lsofpara 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 lsof4.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.

Huésped
fuente
66
¡Bienvenido a Unix y Linux Stack Exchange! Su respuesta a esta pregunta es excelente. Espero que vuelvas para responder más preguntas.
36

xdotool no funcionó para mí. Esto hizo:

correr

xprop _NET_WM_PID

y haz clic en la ventana.

Esto se basa en la respuesta en http://www.linuxquestions.org/questions/linux-software-2/advanced-question-finding-pid-of-an-x-window-328983/

Noam
fuente
Funciona para mí al enchufar mi iPhone, aparece un mensaje de ventana que no responde.
modulitos
1
Útil para evidencia que a veces colgaba por completo. kill $(xprop _NET_WM_PID|cut -d " " -f 3)
Gabriel Devillers
Esto es lo que estaba buscando, xkill flow
Rombus
13

Si tiene instalado xdotool , entonces

xdotool selectwindow getwindowpid

seguido haciendo clic en la ventana en cuestión devolverá el PID.

(Hay otras formas de seleccionar la ventana en cuestión, por ejemplo, si tiene su ID de ventana, simplemente puede hacerlo xdotool getwindowpid <number>. También puede seleccionar por nombre o clase, etc.)

Creo que esto requiere algo de juego agradable en nombre de WM. No he experimentado mucho, o lo necesitaba.

precioso
fuente
2
xdo_getwinprop(xdo, window, atom_NET_WM_PID, &nitems, &type, &size)⇒ es solo un envoltorio para leer _NET_WM_PID(útil, pero no es lo que pedí).
Gilles 'SO- deja de ser malvado'
11

El _NET_WM_PIDadministrador de ventanas no establece el (como otro cliente X11, ¿cómo lo sabría?).

En lugar de ello, se espera que los clientes X11 compatibles (aplicaciones) para establecer _NET_WM_PIDy WM_CLIENT_MACHINEen sus propias ventanas. Asumiendo una aplicación que se comporte bien, esto será cierto tanto si se está ejecutando un administrador de ventanas como si no.

Si WM_CLIENT_MACHINEes su propio nombre de host, entonces el PID debe ser significativo.
De lo contrario, "Me gustaría la IP y el puerto asociados con el extremo remoto": no estoy seguro de lo que eso significa. Por ejemplo, si tiene una sesión ssh abierta con el reenvío X habilitado, las ventanas abiertas por las aplicaciones reenviadas se marcarán con PID remoto y nombre de host, pero no necesariamente tiene ninguna forma de conectarse de nuevo a ese host remoto.

efímero
fuente
2
_NET_WM_PIDlo establece la aplicación: correcto, ¡eso tiene más sentido! Pero no es el protocolo X11, es la relativamente reciente especificación de FreeDesktop .
Gilles 'SO- deja de ser malvado'
En el caso de ssh, en lo que respecta al servidor X, esta es una conexión local del proceso sshd. Aunque _NET_WM_PIDparece estar configurado para el PID remoto y WM_CLIENT_MACHINEpara la conexión remota (probado con xterm).
Gilles 'SO- deja de ser malvado'
4

Pude usar la xdotoolversión beta de Ubuntu 11.04, pero selectwindowno era un comando válido, tuve que hackear un script con:

$ while true; do sleep 1; xdotool getactivewindow; done

luego mire la identificación de la ventana mientras seleccioné la ventana que quería, luego decodifiqué el PID responsable con:

$ xdotool getwindowpid <the-window-id>
Jon Bailey
fuente