Если ваш X-сервер не поддерживает XResQueryClientIds
из X-Resource v1.2 extension Я не знаю легкий способ надежно идентификатор процесса запроса. Однако есть и другие способы.
Если у вас просто есть окно перед вами и вы еще не знаете его идентификатор - это легко узнать. Просто откройте терминал рядом с рассматриваемым окном, запустите xwininfo
и нажмите на это окно. xwininfo
покажет вам идентификатор окна.
Итак, давайте предположим, что вы знаете идентификатор окна, например, 0x1600045, и хотите узнать, каков процесс, которым он принадлежит.
Самый простой способ проверить, кому принадлежит это окно, - запустить для него XKillClient, т. Е .:
xkill -id 0x1600045
и посмотрите, какой процесс только что умер. Конечно, если ты не против умереть.
Другой простой, но ненадежный способ - проверить его свойства _NET_WM_PID
и WM_CLIENT_MACHINE
:
xprop -id 0x1600045
Вот что делают такие инструменты, как xlsclients
и xrestop
do.
К сожалению, эта информация может быть неверной не только потому, что процесс был злым и изменил его, но также и потому, что он глючил. Например, после некоторого сбоя / перезапуска 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) (клиенты [я] -> osPrivate)) -.> * FD 1044 *
Возможно, подключено много 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.
* * Пример одна тысяча пятьдесят пять: * * одна тысяча пятьдесят-шесть
Найдите 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
Идентификатор окна - 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
Теперь вы знаете, что клиент подключен к серверному сокету 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, как показано выше, что означает, что это локальный клиент.
Чтобы найти пару для этого сокета Unix, вы можете использовать метод MvG
(вам также понадобится отладочная информация для вашего установленного ядра):
$ sudo gdb -c /proc/kcore
(gdb) print ((struct unix_sock*)0xffff810008339340)->peer
$1 = (struct sock *) 0xffff810008339600
(gdb) quit
Теперь, когда вы знаете клиентский сокет, используйте lsof
, чтобы найти PID, удерживающий его:
$ sudo lsof -n | grep 0xffff810008339600
firefox 7725 username 146u unix 0xffff810008339600 8512421 socket
Вот и все. Процесс с этим окном называется «firefox» с идентификатором процесса 7725