Какой процесс создал это окно X11?

75

Учитывая идентификатор окна X11, есть ли способ найти идентификатор процесса, который его создал?

Конечно, это не всегда возможно, например, если окно было установлено по TCP-соединению. В этом случае я хотел бы, чтобы IP и порт были связаны с удаленным концом.

Вопрос был задан ранее о переполнении стека , и предложенный метод должен был использовать это _NET_WM_PIDсвойство. Но это устанавливается приложением. Есть ли способ сделать это, если приложение не играет хорошо?

Жиль "ТАК - перестань быть злым"
источник
Связанный: 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 я видел осиротевшие окна (я полагаю, из плагина flash) с _NET_WM_PIDуказанием на процесс, который давно умер.

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

xwininfo -root -tree

и проверьте свойства родителей рассматриваемого окна. Это также может дать вам некоторые советы о происхождении окна.

Но! Хотя вы можете не узнать, какой процесс создал это окно, все же есть способ узнать, откуда этот процесс подключился к X-серверу. И этот путь для настоящих хакеров. :)

Идентификатор окна 0x1600045, который вы знаете с нулевыми младшими битами (т. Е. 0x1600000), является «клиентской базой». И все идентификаторы ресурсов, выделенные для этого клиента, «основаны» на нем (0x1600001, 0x1600002, 0x1600003 и т. Д.). X-сервер хранит информацию о своих клиентах в массиве clients [], а для каждого клиента его «база» хранится в переменной clients [i] -> clientAsMask. Чтобы найти X-сокет, соответствующий этому клиенту, вам нужно подключиться к X-серверу с помощью gdb, пройтись по массиву clients [], найти клиент с этим clientAsMaskи напечатать его дескриптор сокета, хранящийся в ((OsCommPtr) (clients [i] - > osPrivate)) -> ФД.

Может быть подключено много 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-серверу изнутри 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-Distribution или пакет -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» с идентификатором процесса 7725


Редактирование 2017 : Есть больше вариантов, как видно на сайте Кто получил другой конец этой пары сокетов Unix? , В Linux 3.3 или выше и lsof4.89 или выше вы можете заменить пункты с 3 по 5 выше:

lsof +E -a -p 1237 -d 31

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

гость
источник
6
Добро пожаловать в Unix и Linux Stack Exchange! Ваш ответ на этот вопрос превосходен. Я надеюсь, что вы вернетесь, чтобы ответить на дополнительные вопросы.
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)⇒ это просто оболочка для чтения _NET_WM_PID(полезно, но не то, что я просил).
Жиль "ТАК - перестань быть злым"
11

_NET_WM_PIDНе установлен оконный менеджер (как только другой клиент X11, как бы это знать?).

Вместо этого совместимые клиенты (приложения) X11 должны устанавливаться _NET_WM_PIDи WM_CLIENT_MACHINEна своих собственных окнах. При условии, что приложение работает хорошо, это будет верно независимо от того, запущен оконный менеджер или нет.

Если WM_CLIENT_MACHINEваше собственное имя хоста, то PID должен быть значимым.
В противном случае, «я хотел бы IP и порт, связанный с удаленным концом» - я не уверен, что это значит. Например, если у вас открыт сеанс ssh с включенной переадресацией X, окна, открытые переадресованными приложениями, будут помечены с помощью удаленного PID и имени хоста, но вам не обязательно каким-либо образом подключаться к этому удаленному хосту.

ephemient
источник
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

затем проследите за тем, как проходит окно ID, пока я выбираю нужное окно, а затем расшифровываем ответственный PID:

$ xdotool getwindowpid <the-window-id>
Джон Бейли
источник