it-swarm-pt.com

Qual processo criou essa janela do X11?

Dado um ID da janela X11, existe uma maneira de encontrar o ID do processo que o criou?

Obviamente, isso nem sempre é possível, por exemplo, se a janela aparecer através de uma conexão TCP. Nesse caso, eu gostaria do IP e da porta associados ao terminal remoto).

A pergunta foi feita anteriormente no Stack Overflow , e um método proposto era usar o _NET_WM_PID propriedade. Mas isso é definido pelo aplicativo. Existe uma maneira de fazer isso se o aplicativo não funcionar bem?

80

A menos que o seu servidor X suporte XResQueryClientIds de extensão X-Resource v1.2 eu não sei fácil maneira de confiável solicite o ID do processo. Existem outras maneiras, no entanto.

Se você tem apenas uma janela à sua frente e ainda não sabe o seu ID - é fácil descobrir. Basta abrir um terminal próximo à janela em questão, executar 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 _NET_WM_PID e WM_CLIENT_MACHINE propriedades:

xprop -id 0x1600045

É o que ferramentas como xlsclients e xrestop fazem.

Infelizmente, essas informações podem estar incorretas não apenas porque o processo foi ruim e as alterou, mas também porque eram de bugs. Por exemplo, depois de algum travamento/reinicialização do firefox, vi janelas órfãs (do plugin flash, eu acho) com _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 consiga descobrir 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 esse clientAsMask e imprimir seu descritor de soquete, armazenado em ((OsCommPtr) (clientes [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 a partir do DENTRO do servidor X. O gdb suspende o processo ao qual ele se conecta, portanto, se você se conectar a ele 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 conecte-se à sua máquina pelo ssh.

Exemplo:

  1. 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
    
  2. 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
    
  3. Agora você sabe que o cliente está conectado a um soquete do servidor 31. 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 acessar a 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.

  4. Para encontrar um par para esse soquete unix, você pode usar o 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
    
  5. Agora que você conhece o soquete do cliente, use lsof para encontrar o PID segurando:

    $ 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 de processo 7725


2017 Edit : Agora há mais opções, como visto em Quem tem a outra extremidade desse socket unix? . No 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 servidor X com o ID 1237.

67
Guest

o xdotool não funcionou para mim. Isso fez:

Corre

xprop _NET_WM_PID

e clique na janela.

Isso é baseado na resposta em http://www.linuxquestions.org/questions/linux-software-2/advanced-question-finding-pid-of-an-x-window-328983/

37
Noam

Se você tiver xdotool instalado, então

xdotool selectwindow getwindowpid

seguido de clicar na janela em questão retornará o PID.

(Existem outras maneiras de selecionar a janela em questão, por exemplo, se você tiver o ID da janela, basta fazer xdotool getwindowpid <number>. Você também pode selecionar por nome ou classe, etc.)

Eu acho que isso requer algum jogo agradável em nome do WM. Não experimentei muito ou precisei.

13
frabjous

O _NET_WM_PID não é definido pelo gerenciador de janelas (como apenas outro cliente X11, como ele saberia?).

Em vez disso, espera-se que os clientes X11 compatíveis (aplicativos) definam _NET_WM_PID e WM_CLIENT_MACHINE em suas próprias janelas. Supondo que um aplicativo com bom comportamento, isso será verdade se um gerenciador de janelas está sendo executado ou não.

E se WM_CLIENT_MACHINE é seu próprio nome de host, então o PID deve ser significativo.
Caso contrário, "eu gostaria do IP e da porta associados à extremidade remota" - não tenho certeza do que isso significa. Por exemplo, se você tiver uma sessão ssh aberta com o encaminhamento X ativado, as janelas abertas pelos aplicativos encaminhados serão marcadas com PID remoto e nome do host, mas você não necessariamente tem como conectar-se novamente a esse host remoto.

12
ephemient

Consegui usar o xdotool no Ubuntu 11.04 beta, mas selectwindow não era um comando válido, tive que hackear um script com:

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

observe a identificação da janela passar enquanto selecionei a janela que queria e decodifiquei o PID responsável com:

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