当然,这并非总是可能的,例如,如果窗口是通过TCP连接来的。对于这种情况,我需要与远程端关联的IP和端口。但这是由应用程序设置的。如果应用程序运行不正常,有没有办法解决?
#1 楼
除非您的X服务器支持X-Resource v1.2扩展中的XResQueryClientIds
,否则我不知道可靠地请求进程ID的简便方法。但是,还有其他方法。如果您前面只有一个窗口并且还不知道其ID,那么很容易找到它。只需打开相关窗口旁边的终端,在其中运行
xwininfo
并单击该窗口即可。 xwininfo
将显示窗口ID。因此,假设您知道一个窗口ID,例如0x1600045,并想要查找拥有它的进程是什么。
检查该窗口属于谁的最简单方法是为其运行XKillClient,即:
/>
,看看哪个进程死了。但是,只有在您不介意杀死它的情况下!
另一个简单但不可靠的方法是检查其
_NET_WM_PID
和WM_CLIENT_MACHINE
属性: />这就是xlsclients
和xrestop
之类的工具所做的事情。此信息可能不正确,不仅是因为该过程有害并且更改了这些信息,还因为它有故障。例如,在某些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_PID
和WM_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
评论
相关:来自窗口ID /名称的PID