Que processo criou esta janela do X11?

66

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

Claro que isso nem sempre é possível, por exemplo, se a janela aparecer em uma conexão TCP. Para esse caso, gostaria do IP e da porta associados ao terminal remoto.

A pergunta foi feita antes na pilha Estouro e um método proposto era usar a propriedade _NET_WM_PID . Mas isso é definido pelo aplicativo. Existe uma maneira de fazer isso se o aplicativo não for legal?

    
por Gilles 06.01.2011 / 22:07

5 respostas

49

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.

Infelizmente, esta informação pode estar incorreta não só porque o processo foi mal e mudou isso, mas também porque estava com erros. Por exemplo, após alguns crash / restart do firefox, eu vi janelas órfãs (do plugin flash, eu acho) com _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:

  1. 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
    
  2. 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
    
  3. 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.

  4. 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
    
  5. 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.

    
por 31.07.2013 / 01:29
33

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

Executar

xprop _NET_WM_PID

e clique na janela.

Isto é baseado na resposta em link

    
por 10.09.2012 / 19:34
12

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 alguns jogando legal em nome do WM. Eu não experimentei muito ou precisei.

    
por 07.01.2011 / 00:10
11

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 clientes X11 compatíveis (aplicativos) definam _NET_WM_PID e WM_CLIENT_MACHINE em suas próprias janelas. Assumindo um aplicativo bem comportado, isso será verdadeiro se um gerenciador de janelas estiver em execução ou não.

Se WM_CLIENT_MACHINE for seu próprio nome de host, o PID deverá ser significativo.
Caso contrário, "Eu gostaria do IP e da porta associados ao terminal remoto" - 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 o PID e o nome do host remotos, mas você não terá necessariamente nenhuma maneira de se conectar ao host remoto.

    
por 08.01.2011 / 05:18
3

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

em seguida, observe a ID da janela passar enquanto selecionei a janela que queria e decodifiquei o PID responsável com:

$ xdotool getwindowpid <the-window-id>
    
por 17.04.2011 / 16:49

Tags