Який процес створив це вікно X11?


75

Враховуючи ідентифікатор вікна X11, чи можна знайти ідентифікатор процесу, який його створив?

Звичайно, це не завжди можливо, наприклад, якщо вікно перейшло через з'єднання TCP. У цьому випадку я хотів би IP та порт, пов'язаний з віддаленим кінцем.

Запитання було задано раніше в Stack Overflow , і запропонованим методом було використання _NET_WM_PIDвластивості. Але це встановлено додатком. Чи є спосіб це зробити, якщо програма не грає добре?


Відповіді:


60

Якщо ваш X-сервер не підтримує XResQueryClientIdsз розширенням v1.2 X-ресурсів я не знаю простий спосіб надійно запросити ідентифікатор процесу. Однак є й інші способи.

Якщо у вас просто вікно перед собою і ще не знаєте його посвідчення особи - це легко знайти. Просто відкрийте термінал поруч із відповідним вікном, запустіть xwininfoйого та натисніть на це вікно. xwininfoпокаже вам вікно-ідентифікатор.

Тож припустимо, що ви знаєте ідентифікатор вікна, наприклад 0x1600045, і хочете знайти, який процес має його.

Найпростіший спосіб перевірити, кому належить це вікно - це запустити для нього XKillClient, тобто:

xkill -id 0x1600045

і подивіться, який процес щойно загинув. Але тільки якщо ви не проти вбити це, звичайно!

Ще один простий, але ненадійний спосіб - перевірити його _NET_WM_PIDта WM_CLIENT_MACHINEвластивості:

xprop -id 0x1600045

Ось які інструменти люблять xlsclientsі xrestopроблять.

На жаль, ця інформація може бути невірною не лише тому, що процес був злим і змінив їх, а й тому, що він баггі. Наприклад, після деякої аварії / перезавантаження Firefox я бачив осиротілих вікон (з флеш-плагіну, я думаю) із _NET_WM_PIDвказівкою на процес, який давно помер.

Альтернативний спосіб - бігти

xwininfo -root -tree

і перевірити властивості батьків відповідного вікна. Це також може дати вам підказки щодо походження вікон.

Але! Хоча ви можете не знайти, який процес створив це вікно, все ж є спосіб знайти, звідки цей процес підключився до X-сервера. І такий шлях - для справжніх хакерів. :)

Ідентифікатор вікна 0x1600045, який ви знаєте з нульовими бітами (тобто 0x1600000), є "клієнтською базою". І всі ідентифікатори ресурсів, виділені для цього клієнта, "базуються" на ньому (0x1600001, 0x1600002, 0x1600003 тощо). X-сервер зберігає інформацію про своїх клієнтів у масиві client [], а для кожного клієнта його "база" зберігається у змінній client [i] -> clientAsMask. Щоб знайти X-socket, відповідний цьому клієнту, вам потрібно підключитися до X-сервера gdb, пройти по масиву client [], знайти клієнта з цим clientAsMaskі надрукувати його дескриптор сокета, що зберігається в ((OsCommPtr) (clients [i] - > osPrivate)) -> fd.

Можливо, підключено багато X-клієнтів, тому для того, щоб не перевіряти їх усі вручну, давайте скористаємось функцією 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

Знайшовши сокет, ви можете перевірити, хто з ним підключений, і нарешті знайти процес.

ПОПЕРЕДЖЕННЯ : НЕ прикріплюйте gdb до X-сервера з INSIDE X-сервера. gdb призупиняє процес, до якого він приєднується, тому якщо ви приєднаєтесь до нього зсередини X-сеансу, ви заморозите ваш X-сервер і не зможете взаємодіяти з gdb. Ви повинні або переключитися на текстовий термінал ( Ctrl+Alt+F2), або підключитися до машини через ssh.

Приклад:

  1. Знайдіть PID вашого 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. Ідентифікатор вікна 0x1600045, тому клієнтська база - 0x1600000. Приєднайте до X-сервера та знайдіть дескриптор розетки клієнта для цієї клієнтської бази. Вам знадобиться інформація про налагодження, встановлена ​​для X-сервера (-debuginfo пакет для rpm-дистрибуцій або -dbg пакет для deb).

    $ 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. Тепер ви знаєте, що клієнт підключений до серверного сокета 31. Використовуйте, lsofщоб знайти, що таке сокет:

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

    (тут "X" - це ім'я процесу, "1237" - його pid, "root" - це користувач, з якого він працює, "31u" - дескриптор сокета)

    Там ви можете побачити, що клієнт підключений через TCP, тоді ви можете перейти до машини, з якої він підключений, і перевірити netstat -napтам, щоб знайти процес. Але швидше за все там ви побачите unix-сокет, як показано вище, це означає, що це локальний клієнт.

  4. Щоб знайти пару для цього unix-сокета, ви можете використовувати техніку MvG (вам також знадобиться інформація про налагодження для встановленого ядра):

    $ sudo gdb -c /proc/kcore
    (gdb) print ((struct unix_sock*)0xffff810008339340)->peer
    $1 = (struct sock *) 0xffff810008339600
    (gdb) quit
    
  5. Тепер, коли ви знаєте клієнтський сокет, використовуйте, lsofщоб знайти PID, який тримає його:

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

Це воно. Процес, що зберігає це вікно, є "firefox" з id-процесом 7725


2017 Редагувати : Існує більше варіантів, як видно на сайті Хто має інший кінець цієї unix-сокета? . У версії Linux 3.3 або вище та lsofверсії 4.89 або вище, ви можете замінити пункти 3–5 вище:

lsof +E -a -p 1237 -d 31

щоб дізнатись, хто знаходиться на іншому кінці сокета на fd 31 процесу X-сервера з ідентифікатором 1237.


6
Ласкаво просимо на обмін стеками Unix та Linux! Ваша відповідь на це запитання відмінна. Сподіваюся, ви повернетесь, щоб відповісти на більше запитань.

36

xdotool не працював для мене. Це зробило:

Біжи

xprop _NET_WM_PID

і натисніть на вікно.

Це ґрунтується на відповіді за адресою http://www.linuxquestions.org/questions/linux-software-2/advanced-question-finding-pid-of-an-x-window-328983/


Працює для мене під час підключення до Iphone, що спричинив невідповідний вікно.
modulitos

1
Корисно для думки, що іноді висіло повністю. kill $(xprop _NET_WM_PID|cut -d " " -f 3)
Габріель Дияволс

Це те, що я шукав, xkill flow
Rombus

13

Якщо у вас встановлений xdotool , значить

xdotool selectwindow getwindowpid

з наступним натисканням на відповідне вікно поверне PID.

(Є й інші способи вибору відповідного вікна, наприклад, якщо у вас є його ідентифікатор вікна, ви можете це зробити xdotool getwindowpid <number>. Ви також можете вибрати ім’я чи клас тощо).

Я думаю, що для цього потрібна гра в хороші ігри від імені WM. Я не експериментував багато, чи потрібно було.


2
xdo_getwinprop(xdo, window, atom_NET_WM_PID, &nitems, &type, &size)To це просто обгортка оболонки для читання _NET_WM_PID(корисно, але не те, що я просив).
Жиль

11

Це _NET_WM_PIDне встановлено менеджером вікон (як просто ще один клієнт X11, як це знати?).

Натомість очікується, що сумісні клієнти (додатки) X11 встановлюватимуться _NET_WM_PIDі WM_CLIENT_MACHINEу власних вікнах. Якщо припустити, що добре працює програма, це буде правдою, працює він чи ні.

Якщо WM_CLIENT_MACHINEваше власне ім’я хоста, то PID повинен мати значення.
В іншому випадку "я хотів би, щоб IP та порт пов'язані з віддаленим кінцем" - я не впевнений, що це означає. Наприклад, якщо у вас відкрито сеанс ssh з увімкненою переадресацією X, вікна, відкриті переадресованими програмами, будуть позначені віддаленим PID та ім'ям хоста, але не обов'язково є спосіб підключення назад до цього віддаленого хоста.


2
_NET_WM_PIDвстановлюється програмою: правильно, це має більше сенсу! Але це не протокол X11, це відносно недавня специфікація FreeDesktop .
Жил

У випадку ssh, що стосується X-сервера, це локальне з'єднання від sshd-процесу. Хоча, _NET_WM_PIDздається, він встановлений для віддаленого PID та WM_CLIENT_MACHINEвіддаленого з'єднання (тестується xterm).
Жил

4

Мені вдалося використовувати xdotoolбета-версію Ubuntu 11.04, але selectwindowце не була дійсна команда, мені довелося зламати сценарій із:

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

потім перегляньте ідентифікатор вікна, поки я вибрав потрібне вікно, а потім розшифруйте відповідальний PID за допомогою:

$ xdotool getwindowpid <the-window-id>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.