A menos que o seu X-server suporte XResQueryClientIds
da extensão X-Resource v1.2 Não conheço nenhum fácil caminho para confiantemente solicitar ID do processo. Existem outras maneiras no entanto.
Se você tiver apenas uma janela à sua frente e ainda não sabe o seu ID - é fácil descobrir. Basta abrir um terminal ao lado da janela em questão, executar xwininfo
lá e clicar nessa janela. xwininfo
mostrará o id da janela.
Então, vamos supor que você conheça um id de janela, por exemplo 0x1600045, e quer encontrar, qual é o processo que o possui.
A maneira mais fácil de verificar a quem essa janela pertence é executar o XKillClient, ou seja:
xkill -id 0x1600045
e veja qual processo acabou de morrer. Mas só se você não se importar de matar, é claro!
Outra maneira fácil, porém não confiável, é verificar suas propriedades _NET_WM_PID
e WM_CLIENT_MACHINE
:
xprop -id 0x1600045
Isso é o que ferramentas como xlsclients
e xrestop
fazem.
_NET_WM_PID
apontando para um processo, que morreu há muito tempo.
A maneira alternativa é executar
xwininfo -root -tree
e verifique as propriedades dos pais da janela em questão. Isso também pode lhe dar algumas dicas sobre origens de janelas.
Mas! Embora você não encontre o processo que criou essa janela, ainda há uma maneira de descobrir de onde esse processo se conectou ao servidor X. E esse caminho é para hackers reais. :)
O ID da janela 0x1600045 que você conhece com bits menores zerados (isto é, 0x1600000) é uma "base de clientes". E todos os IDs de recursos alocados para esse cliente são "baseados" (0x1600001, 0x1600002, 0x1600003, etc). O X-server armazena informações sobre seus clientes na matriz clients [], e para cada cliente sua "base" é armazenada na variável clients [i] - > clientAsMask. Para encontrar o X-socket, correspondente a esse cliente, você precisa anexar ao X-server com gdb
, andar sobre os clientes [] array, localizar o cliente com esse clientAsMask
e imprimir seu descritor de soquete, armazenado em ((OsCommPtr) (clientes [i] - > osPrivate)) - > fd.
Pode haver muitos clientes X conectados, por isso, para não verificá-los manualmente, vamos usar uma função 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
Quando você encontrar o socket, você pode verificar quem está conectado a ele e finalmente encontrar o processo.
AVISO : NÃO anexe o gdb ao servidor X a partir do INTERIOR do X-server. O gdb suspende o processo ao qual ele se conecta, então se você se conectar a ele de dentro da X-session, você irá congelar o seu X-server e não poderá interagir com o gdb. Você deve alternar para o terminal de texto ( Ctrl+Alt+F2
) ou conectar-se à sua máquina por ssh.
Exemplo:
-
Encontre o PID do seu X-server:
$ ps ax | grep X 1237 tty1 Ssl+ 11:36 /usr/bin/X :0 vt1 -nr -nolisten tcp -auth /var/run/kdm/A:0-h6syCa
-
O ID da janela é 0x1600045, portanto, a base do cliente é 0x1600000. Anexe ao servidor X e localize o descritor de soquete do cliente para essa base de clientes. Você precisará de informações de depuração instalado para o X-server (pacote -debuginfo para distribuições-rpm ou pacote -dbg para deb's).
$ 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
-
Agora você sabe que o cliente está conectado a um soquete de servidor 31. Use
lsof
para descobrir qual é o soquete:$ sudo lsof -n | grep 1237 | grep 31 X 1237 root 31u unix 0xffff810008339340 8512422 socket
(aqui "X" é o nome do processo, "1237" é o pid, "root" é o usuário que está sendo executado, "31u" é um descritor de soquete)
Lá você pode ver que o cliente está conectado via TCP, então você pode ir até a máquina de onde ele está conectado e verificar
netstat -nap
para encontrar o processo. Mas provavelmente você verá um socket unix, como mostrado acima, o que significa que é um cliente local. -
Para encontrar um par para esse soquete unix, você pode usar a técnica do MvG (você também precisará de informações de depuração para o seu kernel instalado):
$ sudo gdb -c /proc/kcore (gdb) print ((struct unix_sock*)0xffff810008339340)->peer $1 = (struct sock *) 0xffff810008339600 (gdb) quit
-
Agora que você conhece o soquete do cliente, use
lsof
para encontrar o PID:$ sudo lsof -n | grep 0xffff810008339600 firefox 7725 username 146u unix 0xffff810008339600 8512421 socket
É isso. O processo que mantém essa janela é "firefox" com o ID do processo 7725
2017 Editar : Existem mais opções agora, como visto em Quem tem a outra extremidade deste unix socketpair Com o Linux 3.3 ou superior e com lsof
4.89 ou acima, você pode substituir os pontos 3 a 5 acima por:
lsof +E -a -p 1237 -d 31
para descobrir quem está no outro extremo do socket no fd 31 do processo do X-server com o ID 1237.