Que processo criou essa janela do X11?


75

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 vier 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 a _NET_WM_PIDpropriedade Mas isso é definido pelo aplicativo. Existe uma maneira de fazer isso se o aplicativo não funcionar bem?


Respostas:


60

A menos que o seu servidor X suporte XResQueryClientIdsda 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 xwininfolá e clicar nessa janela. xwininfomostrará 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_PIDe WM_CLIENT_MACHINE:

xprop -id 0x1600045

É isso que as ferramentas gostam xlsclientse xrestopfazem.

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_PIDapontando 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 clientAsMaske 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:

  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 31 do servidor. Use lsofpara 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 -naplá 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 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
    
  5. Agora que você conhece o soquete do cliente, use o lsofPID 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 lsof4.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.


6
Bem-vindo ao Unix e Linux Stack Exchange! Sua resposta a esta pergunta é excelente. Espero que você volte para responder a mais perguntas.

36

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/


Funciona para mim ao conectar o meu iPhone e abrir um prompt de janela que não responde.
Modulitos 17/10

1
Útil para demonstrar que às vezes pendia completamente. kill $(xprop _NET_WM_PID|cut -d " " -f 3)
Gabriel Devillers

Isto é o que eu estava procurando, o fluxo xkill
Rombus

13

Se você tiver o 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 fazê-lo xdotool getwindowpid <number>. Você também pode selecionar por nome ou classe, etc.)

Eu acho que isso requer um bom desempenho em nome do WM. Não experimentei muito ou precisei.


2
xdo_getwinprop(xdo, window, atom_NET_WM_PID, &nitems, &type, &size)⇒ é apenas um invólucro de shell para ler _NET_WM_PID(útil, mas não o que eu pedi).
Gilles

11

O _NET_WM_PIDnã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) sejam configurados _NET_WM_PIDe WM_CLIENT_MACHINEem 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.

Se WM_CLIENT_MACHINEé o seu próprio nome de host, 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.


2
_NET_WM_PIDé definido pelo aplicativo: certo, isso faz mais sentido! Mas não é o protocolo X11, é a especificação relativamente recente do FreeDesktop .
Gilles

No caso do ssh, no que diz respeito ao servidor X, esta é uma conexão local do processo sshd. Embora _NET_WM_PIDpareça estar definido para o PID remoto e WM_CLIENT_MACHINEa conexão remota (testado com xterm).
Gilles

4

Consegui usar o xdotoolUbuntu 11.04 beta, mas selectwindownã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>
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.