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

Я испытал затруднения, заставив экран поддерживать utf-8 и 256 цветов, но tmux работал из поля.

78
23.05.2017, 15:40
5 ответов

Если Ваш X-сервер не поддерживает XResQueryClientIds от X-ресурса v1.2 расширение я не знаю простого способа надежно запросить идентификатор процесса. Существуют другие пути как бы то ни было.

Если Вы просто имеете окно перед Вами и еще не знаете его идентификатор — легко узнать это. Просто откройте терминал рядом с рассматриваемым окном, работайте 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-сервер хранит информацию о своих клиентах в клиентах [] массив, и для каждого клиента ее "основа" хранится в клиентах [я]-> clientAsMask переменная. Для нахождения X-сокета, соответствуя тому клиенту, необходимо подключить к X-серверу с gdb, клиенты технической победы [] массив, найдите клиент с этим clientAsMask и распечатайте его дескриптор сокета, сохраненный в ((OsCommPtr) (клиенты [я]-> 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-серверу ИЗ 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 пакет для дистрибутивов об/мин или-dbg пакет для 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. Теперь Вы знаете, что клиент подключен к сокету сервера 31. Использовать lsof для нахождения, каков тот сокет:

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

    (здесь "X" имя процесса, "1237" его pid, "корень" является пользователем, от которого это работает, "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 socketpair?. С Linux 3.3 или выше и с lsof 4.89 или выше, можно заменить точки 3 - 5 выше с:

lsof +E -a -p 1237 -d 31

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

65
27.01.2020, 19:30
  • 1
    Приветствуйте Exchange Стопки Unix и Linux! Ваш ответ на этот вопрос превосходен. Я надеюсь, что Вы возвращаетесь для ответа на большее количество вопросов. –   31.07.2013, 03:00

Если у Вас есть установленный xdotool, то

xdotool selectwindow getwindowpid

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

(Существуют другие способы выбрать рассматриваемое окно, например, если у Вас есть его окно ID, можно просто сделать xdotool getwindowpid <number>. Можно также выбрать по имени или класс, и т.д.),

Я действительно думаю, что это требует некоторых играющих по правилам от имени WM. Я не экспериментировал очень, или должен был.

13
27.01.2020, 19:30
  • 1
    xdo_getwinprop(xdo, window, atom_NET_WM_PID, &nitems, &type, &size) ⇒ это - просто обертка оболочки для чтения _NET_WM_PID (полезный, но не, что я попросил). –  Gilles 'SO- stop being evil' 07.01.2011, 01:44

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

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

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

12
27.01.2020, 19:30
  • 1
    _NET_WM_PID установлен приложением: право, которое действительно имеет больше смысла! Но это не протокол X11, это - относительно недавняя спецификация FreeDesktop. –  Gilles 'SO- stop being evil' 08.01.2011, 14:26
  • 2
    В ssh случае, насколько затронут X-сервер, это - локальное соединение от процесса sshd. Хотя _NET_WM_PID кажется, установлен на удаленный PID и WM_CLIENT_MACHINE к удаленному соединению (протестированный с xterm). –  Gilles 'SO- stop being evil' 08.01.2011, 14:26

Я смог использовать xdotool под бетой Ubuntu 11.04, но selectwindow если бы  допустимый команда не был, то я должен был взломать сценарий с:

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

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

$ xdotool getwindowpid <the-window-id>
5
27.01.2020, 19:30

xdotool не работал на меня. Это сделало:

Выполненный

xprop _NET_WM_PID

и нажмите на окно.

Это основано на ответе по http://www.linuxquestions.org/questions/linux-software-2/advanced-question-finding-pid-of-an-x-window-328983/

37
27.01.2020, 19:30
  • 1
    Работы для меня при включении моего iPhone подняли небыстро реагирующую подсказку окна. –  modulitos 17.10.2014, 08:43
  • 2
    Полезный для проявляют, это иногда зависало полностью. kill $(xprop _NET_WM_PID|cut -d " " -f 3) –  Gabriel Devillers 09.10.2016, 14:38

Теги

Похожие вопросы