A menos que o seu servidor X suporte XResQueryClientIds
da extensão X-Resource v1.2, não conheço uma maneira fácil de solicitar com segurança o ID do processo. Existem outras maneiras, no entanto.
Se você apenas tem 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, correr para xwininfo
lá e clicar nessa janela. xwininfo
mostrará o ID da janela.
Então, vamos supor que você conhece um ID de janela, por exemplo, 0x1600045 e deseja descobrir 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 ver qual processo acabou de morrer. Mas só se você não se importa de matá-lo, é 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 que as ferramentas gostam xlsclients
e xrestop
fazem.
Infelizmente, essas informações podem estar incorretas não apenas porque o processo foi mal e as alterou, mas também porque eram de buggy. Por exemplo, após algum travamento / reinicialização do firefox, vi janelas órfãs (do plugin flash, eu acho) _NET_WM_PID
apontando para um processo que morreu há muito tempo.
Maneira alternativa é correr
xwininfo -root -tree
e verifique as propriedades dos pais da janela em questão. Isso também pode lhe dar algumas dicas sobre as origens da janela.
Mas! Embora você não encontre qual processo criou essa janela, ainda há uma maneira de descobrir de onde esse processo se conectou ao X-server. E é assim para hackers reais. :)
O ID da janela 0x1600045 que você conhece com bits inferiores zerados (ou seja, 0x1600000) é uma "base de clientes". E todas as IDs de recursos alocadas para esse cliente são "baseadas" nele (0x1600001, 0x1600002, 0x1600003 etc.). O servidor X 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 soquete X, correspondente a esse cliente, você precisa se conectar ao servidor X com gdb
, percorrer a matriz clients [], encontrar o cliente com isso clientAsMask
e imprimir seu descritor de soquete, armazenado em ((OsCommPtr) (clients [i] - > osPrivate)) -> fd.
Pode haver muitos clientes X conectados, portanto, para não verificar todos eles 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ê encontra o soquete, pode verificar quem está conectado a ele e finalmente encontrar o processo.
AVISO : NÃO anexe gdb ao servidor X DENTRO do servidor X. O gdb suspende o processo ao qual ele se conecta, portanto, se você se conectar a ele de dentro da X-session, congelará seu servidor X e não poderá interagir com o gdb. Você deve mudar para o terminal de texto ( Ctrl+Alt+F2
) ou conectar-se à sua máquina pelo ssh.
Exemplo:
Encontre o PID do seu 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
O ID da janela é 0x1600045, portanto, a base de clientes é 0x1600000. Anexe ao servidor X e encontre o descritor de soquete do cliente para essa base de clientes. Você precisará das informações de depuração instaladas no X-server (pacote -debuginfo para rpm-distributions 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 31 do servidor. Use lsof
para encontrar o que é esse soquete:
$ sudo lsof -n | grep 1237 | grep 31
X 1237 root 31u unix 0xffff810008339340 8512422 socket
(aqui "X" é o nome do processo, "1237" é o seu pid, "root" é o usuário do qual ele está sendo executado, "31u" é um descritor de soquete)
Lá, você pode ver que o cliente está conectado por TCP, depois pode ir à máquina da qual está conectado e verificar netstat -nap
lá para encontrar o processo. Mas provavelmente você verá um soquete unix lá, 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 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 o lsof
PID para encontrá-lo:
$ sudo lsof -n | grep 0xffff810008339600
firefox 7725 username 146u unix 0xffff810008339600 8512421 socket
É isso aí. O processo que mantém essa janela é "firefox" com o ID do processo 7725
Edição de 2017 : Existem mais opções agora, como visto em Quem tem a outra extremidade deste socket unix? . Com o Linux 3.3 ou superior e com lsof
4.89 ou superior, você pode substituir os pontos 3 a 5 acima por:
lsof +E -a -p 1237 -d 31
para descobrir quem está do outro lado do soquete no fd 31 do processo do X-server com o ID 1237.