Quel process a créé cette window X11?

Avec un ID de window X11, y a-t-il un moyen de find l'ID du process qui l'a créé?

Bien sûr, ce n'est pas toujours possible, par exemple si la window passe par une connection TCP. Pour ce cas, je voudrais l'adresse IP et le port associé à l'extrémité distante.

La question a été posée avant sur Stack Overflow , et une méthode proposée était d'utiliser la propriété _NET_WM_PID . Mais c'est réglé par l'application. Y at-il un moyen de le faire si l'application ne joue pas bien?

    À less que votre server X ne XResQueryClientIds charge XResQueryClientIds partir de l' XResQueryClientIds X-Resource v1.2, je ne connais aucun moyen facile de requestr un ID de process fiable . Il y a d'autres moyens cependant.

    Si vous avez juste une window devant vous et que vous ne connaissez pas encore son identifiant, il est facile de le find. Il suffit d'ouvrir un terminal à côté de la window en question, d'y exécuter xwininfo et de cliquer sur cette window. xwininfo va vous montrer l'ID de la window.

    Supposons donc que vous connaissiez un identifiant de window, par exemple 0x1600045, et que vous voulez find quel est le process le possédant.

    La façon la plus simple de vérifier à qui appartient cette window est d'exécuter XKillClient pour cela, par exemple:

     xkill -id 0x1600045 

    et voir quel process vient de mourir. Mais seulement si cela ne vous dérange pas de le tuer bien sûr!

    Une autre méthode simple mais peu fiable consiste à vérifier ses propriétés _NET_WM_PID et WM_CLIENT_MACHINE :

     xprop -id 0x1600045 

    C'est ce que font les outils comme xlsclients et xrestop .

    Malheureusement, cette information peut être incorrecte non seulement parce que le process a été mauvais et a changé ceux-ci, mais aussi parce qu'il était bogué. Par exemple, après un crash / redémarrage de firefox, j'ai vu des windows orphelines (du plugin flash, je suppose) avec _NET_WM_PID pointant vers un process, qui est mort il y a longtime.

    Une autre façon est de courir

     xwininfo -root -tree 

    et vérifier les propriétés des parents de la window en question. Cela peut aussi vous donner quelques conseils sur les origines de la window.

    Mais! Bien que vous ne trouviez peut-être pas le process qui a créé cette window, il existe toujours un moyen de find à quel endroit ce process s'est connecté à X-server. Et cette façon est pour les vrais pirates informatiques. 🙂

    L'identificateur de window 0x1600045 que vous connaissez avec des bits inférieurs mis à zéro (c'est-à-dire 0x1600000) est une "base client". Et tous les ID de ressource, alloués pour ce client, sont "basés" dessus (0x1600001, 0x1600002, 0x1600003, etc.). Le server X stocke des informations sur ses clients dans le tableau des clients [], et pour chaque client, sa «base» est stockée dans la variable clients [i] -> clientAsMask. Pour find X-socket, correspondant à ce client, vous devez vous connecter à X-server avec gdb , parcourir le tableau des clients [], find le client avec ce clientAsMask et imprimer son descripteur de socket, stocké dans ((OsCommPtr) ] -> osPrivate)) -> fd.

    Il peut y avoir plusieurs clients X connectés, donc pour ne pas les vérifier tous manuellement, utilisons une fonction 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 

    Lorsque vous trouvez la socket, vous pouvez vérifier, qui est connecté à elle, et enfin find le process.

    AVERTISSEMENT : N'attachez PAS gdb au server X depuis INSIDE du server X. gdb suspend le process auquel il se connecte, donc si vous y attachez à partir de X-session, vous gelerez votre server X et ne pourrez plus interagir avec gdb. Vous devez soit passer au terminal de text ( Ctrl+Alt+F2 ) soit vous connecter à votre machine via ssh.

    Exemple:

    1. Trouvez le PID de votre server X:

       $ ps ax | grep X 1237 tty1 Ssl+ 11:36 /usr/bin/X :0 vt1 -nr -nolistn tcp -auth /var/run/kdm/A:0-h6syCa 
    2. L'ID de window est 0x1600045, la base client est donc 0x1600000. Joindre au server X et find le descripteur de socket client pour cette base de clients. Vous aurez besoin d'informations de debugging installées pour X-server (package -debuginfo pour rpm-dissortingbutions ou package -dbg pour 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. Maintenant vous savez que le client est connecté à une socket server 31. Utilisez lsof pour find ce que ce socket est:

       $ sudo lsof -n | grep 1237 | grep 31 X 1237 root 31u unix 0xffff810008339340 8512422 socket 

      (ici "X" est le nom du process, "1237" est son pid, "root" est l'user à partir duquel il tourne, "31u" est un descripteur de socket)

      Là vous pouvez voir que le client est connecté sur TCP, alors vous pouvez aller à la machine à laquelle il est connecté et vérifier netstat -nap là pour find le process. Mais très probablement, vous verrez un socket unix là-bas, comme indiqué ci-dessus, ce qui signifie que c'est un client local.

    4. Pour find une paire pour ce socket unix, vous pouvez utiliser la technique de MvG (vous aurez également besoin d'informations de debugging pour votre kernel installé):

       $ sudo gdb -c /proc/kcore (gdb) print ((struct unix_sock*)0xffff810008339340)->peer $1 = (struct sock *) 0xffff810008339600 (gdb) quit 
    5. Maintenant que vous connaissez la socket client, utilisez lsof pour find le PID le contenant:

       $ sudo lsof -n | grep 0xffff810008339600 firefox 7725 username 146u unix 0xffff810008339600 8512421 socket 

    C'est tout. Le process conservant cette window est "firefox" avec l'ID de process 7725


    2017 Edit : Il y a plus d'options maintenant vu à Qui a l'autre bout de cette socket unix? . Avec Linux 3.3 ou supérieur et avec lsof 4.89 ou supérieur, vous pouvez replace les points 3 à 5 ci-dessus par:

     lsof +E -a -p 1237 -d 31 

    pour savoir qui est à l'autre bout du socket sur fd 31 du process du server X avec l'ID 1237.

    xdotool n'a pas fonctionné pour moi. Cela a fait:

    Courir

    xprop _NET_WM_PID

    et click la window.

    Ceci est basé sur la réponse à http://www.linuxquestions.org/questions/linux-software-2/advanced-question-finding-pid-of-an-x-window-328983/

    Le _NET_WM_PID n'est pas défini par le gestionnaire de windows (comme un autre client X11, comment le saura-t-il?).

    Au lieu de cela, les clients X11 conforms (applications) devraient définir _NET_WM_PID et WM_CLIENT_MACHINE sur leurs propres windows. En supposant qu'une application bien comscope, cela sera vrai si un gestionnaire de windows est en cours d'exécution ou non.

    Si WM_CLIENT_MACHINE est votre propre nom d'hôte, le PID doit être significatif.
    Sinon, «je voudrais que l'adresse IP et le port soient associés à l'extrémité distante» – je ne suis pas sûr de ce que cela signifie. Par exemple, si vous avez ouvert une session ssh avec le transfert X activé, les windows ouvertes par les applications transférées seront marquées avec PID distant et nom d'hôte, mais vous ne pouvez pas nécessairement vous connecter à cet hôte distant.

    Si xdotool est installé, alors

    xdotool selectwindow getwindowpid

    suivi d'un clic sur la window en question returnnera le PID.

    (Il xdotool getwindowpid <number> façons de sélectionner la window en question, par exemple, si vous avez son ID de window, vous pouvez simplement utiliser xdotool getwindowpid <number> Vous pouvez également sélectionner par nom ou class, etc.)

    Je pense que cela nécessite de jouer gentiment au nom de la WM. Je n'ai pas beaucoup expérimenté, ou eu besoin de.

    J'ai pu utiliser le xdotool sous Ubuntu 11.04 beta, mais selectwindow n'était pas une command valide, j'ai dû pirater un script avec:

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

    puis regardez l'ID window passer pendant que j'ai sélectionné la window que je voulais, puis décodé le PID responsable avec:

     $ xdotool getwindowpid <the-window-id>