给定X11窗口ID,是否可以找到创建它的进程的ID?

当然,这并非总是可能的,例如,如果窗口是通过TCP连接来的。对于这种情况,我需要与远程端关联的IP和端口。但这是由应用程序设置的。如果应用程序运行不正常,有没有办法解决?

评论

相关:来自窗口ID /名称的PID

#1 楼

除非您的X服务器支持X-Resource v1.2扩展中的XResQueryClientIds,否则我不知道可靠地请求进程ID的简便方法。但是,还有其他方法。

如果您前面只有一个窗口并且还不知道其ID,那么很容易找到它。只需打开相关窗口旁边的终端,在其中运行xwininfo并单击该窗口即可。 xwininfo将显示窗口ID。

因此,假设您知道一个窗口ID,例如0x1600045,并想要查找拥有它的进程是什么。

检查该窗口属于谁的最简单方法是为其运行XKillClient,即:
/>
,看看哪个进程死了。但是,只有在您不介意杀死它的情况下!

另一个简单但不可靠的方法是检查其_NET_WM_PIDWM_CLIENT_MACHINE属性: />这就是xlsclientsxrestop之类的工具所做的事情。

此信息可能不正确,不仅是因为该过程有害并且更改了这些信息,还因为它有故障。例如,在某些Firefox崩溃/重新启动后,我看到了孤立的窗口(我想是来自Flash插件),其中_NET_WM_PID指向了一个很久以前就死掉的进程。

替代方法是运行

xkill -id 0x1600045


并检查相关窗口的父级的属性。这也可能为您提供有关窗口起源的一些提示。

但是!尽管您可能找不到哪个进程创建了该窗口,但是仍然可以找到该进程从何处连接到X-server的方法。而且这种方式适用于真正的黑客。 :)

您知道的低位为零(即0x1600000)的窗口ID 0x1600045是“客户端库”。并且为该客户端分配的所有资源ID均基于该客户端(0x1600001、0x1600002、0x1600003等)。 X-server将有关其客户端的信息存储在clients []数组中,并且对于每个客户端,其“基础”都存储在clients [i]-> clientAsMask变量中。要找到与该客户端相对应的X套接字,您需要使用gdb附加到X服务器,遍历client []数组,找到具有clientAsMask的客户端并打印其套接字描述符,并存储在((OsCommPtr)(clients [i ]-> osPrivate))-> fd。

可能连接了许多X客户端,因此,为了不手动检查它们,让我们使用gdb函数:

xprop -id 0x1600045


找到套接字后,您可以检查谁与之连接,并最终找到该进程。

警告:请勿将gdb从在X服务器中。 gdb会挂起它所附加的进程,因此,如果从X-session内部对其进行附加,则将冻结X服务器,并且将无法与gdb进行交互。您必须切换到文本终端(Ctrl+Alt+F2)或通过ssh连接到计算机。

示例:




查找X的PID -server:

xwininfo -root -tree



窗口ID为0x1600045,因此客户端群为0x1600000。附加到X服务器并找到该客户端库的客户端套接字描述符。您需要为X-server安装调试信息(为rpm发行版安装-debuginfo软件包,对于deb则为-dbg软件包)。

/>现在您知道客户端已连接到服务器套接字31。使用lsof查找该套接字是什么:

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


(此处“ X”是进程名称,“ 1237”是其pid,“ root”是其运行的用户,“ 31u”是套接字描述符)

在那里,您可能会看到客户端通过TCP连接,然后您可以转到与其连接的计算机,并检查其中的位置。但很可能您会在该处看到一个unix套接字,如上所示,这意味着它是本地客户端。 br />(您还需要安装内核的调试信息):

$ ps ax | grep X
 1237 tty1     Ssl+  11:36 /usr/bin/X :0 vt1 -nr -nolisten tcp -auth /var/run/kdm/A:0-h6syCa



现在您知道了客户端套接字,请使用netstat -nap查找PID拿着它:

$ 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
 = 31
(gdb) detach
(gdb) quit



就这样。保留该窗口的进程是带有进程ID 7725的“ firefox”


2017编辑:现在有更多选项,如谁在此unix套接字对的另一端?在Linux 3.3或更高版本以及lsof 4.89或更高版本中,可以将上述第3点到第5点替换为:在X服务器进程的fd 31上,ID为1237。

评论


欢迎Unix和Linux Stack Exchange!您对这个问题的回答非常好。希望您回来回答更多问题。

–user26112
13年7月31日在0:00

#2 楼

xdotool对我不起作用。这样做是:

运行

xprop _NET_WM_PID

,然后在窗口上单击。 http://www.linuxquestions.org/questions/linux-software-2/advanced-question-finding-pid-of-an-x-window-328983/

评论


插入我的Iphone时,它会弹出一个无响应的窗口提示,为我工作。

–模数
14-10-17在5:43

有时完全挂起的证据很有用。杀死$(xprop _NET_WM_PID | cut -d“” -f 3)

–加百利·戴维勒(Gabriel Devillers)
16-10-9在11:38

这就是我要找的xkill flow

–菱形
18年2月2日在12:31

#3 楼

如果您安装了xdotool,则在有问题的窗口上单击鼠标左键,将返回PID。

(还有其他方法选择有问题的窗口,例如,如果您具有其窗口ID,则可以执行xdotool selectwindow getwindowpid。也可以按名称或类等进行选择。)代表WM。我没有做太多尝试,或者需要做。

评论


xdo_getwinprop(xdo,窗口,atom_NET_WM_PID,&nitems,&type,&size)

–吉尔斯'所以-不再是邪恶的'
2011年1月6日23:44

#4 楼

窗口管理器未设置_NET_WM_PID(作为另一个X11客户端,它怎么知道?)。相反,兼容的X11客户端(应用程序)应自行设置_NET_WM_PIDWM_CLIENT_MACHINE视窗。假设应用程序运行良好,那么无论窗口管理器是否正在运行,这都是正确的。

如果WM_CLIENT_MACHINE是您自己的主机名,则PID应该有意义。 '想要与远程端关联的IP和端口” –我不确定这是什么意思。例如,如果您打开了一个启用了X转发的ssh会话,则转发的应用程序打开的窗口将被标记为远程PID和主机名,但您不一定有任何方法可以连接回该远程主机。

评论


_NET_WM_PID由应用程序设置:正确,这更有意义!但这不是X11协议,而是相对较新的FreeDesktop规范。

–吉尔斯'所以-不再是邪恶的'
2011年1月8日,12:26

就ssh而言,就X服务器而言,这是sshd进程的本地连接。尽管_NET_WM_PID似乎设置为远程PID,而WM_CLIENT_MACHINE设置为远程连接(已通过xterm测试)。

–吉尔斯'所以-不再是邪恶的'
2011年1月8日在12:26



#5 楼

我可以在Ubuntu 11.04 beta下使用xdotool,但是selectwindow不是有效的命令,我必须使用以下脚本来破解脚本:在选择所需的窗口时经过,然后使用以下命令解码负责的PID:

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