XサーバーXResQueryClientIds
がX-Resource v1.2拡張機能をサポートしていない限り、プロセスID を確実に要求する簡単な方法はわかりません。ただし、他の方法もあります。
目の前にウィンドウがあり、そのIDがまだわからない場合は、簡単に見つけることができます。問題のウィンドウの横にあるターミナルを開き、xwininfo
そこで実行して、そのウィンドウをクリックするだけです。xwininfo
window-idが表示されます。
したがって、0x1600045などのウィンドウIDを知っていて、それを所有しているプロセスを見つけたいとしましょう。
そのウィンドウが誰に属しているかを確認する最も簡単な方法は、そのためにXKillClientを実行することです:
xkill -id 0x1600045
どのプロセスが停止したかを確認します。ただし、もちろんそれを殺しても構わない場合のみです!
もう一つの簡単ですが、信頼性の低い方法は、そのチェックすることです_NET_WM_PID
し、WM_CLIENT_MACHINE
プロパティを:
xprop -id 0x1600045
これは、ツールが好きなものだxlsclients
とxrestop
行います。
残念ながら、この情報は、プロセスが悪かったために変更されただけでなく、バグがあるために間違っている可能性があります。たとえば、Firefoxのクラッシュ/再起動後_NET_WM_PID
、プロセスを指す孤立したウィンドウ(フラッシュプラグインからの推測)が表示されました。
別の方法は実行することです
xwininfo -root -tree
問題のウィンドウの親のプロパティを確認します。また、ウィンドウの原点に関するヒントも提供される場合があります。
しかし!どのウィンドウがそのウィンドウを作成したかはわからないかもしれませんが、そのプロセスがどこからXサーバーに接続したかを見つける方法はまだあります。そして、その方法は本物のハッカー向けです。:)
下位ビットがゼロ(0x1600000)であることがわかっているwindow-id 0x1600045は「クライアントベース」です。そして、そのクライアントに割り当てられたすべてのリソースIDは、それに基づいています(0x1600001、0x1600002、0x1600003など)。Xサーバーは、クライアントに関する情報をclient []配列に格納し、各クライアントの「ベース」は、clients [i]-> clientAsMask変数に格納されます。そのクライアントに対応するXソケットを見つけるには、でXサーバーにアタッチしgdb
、clients []配列を調べclientAsMask
、それでクライアントを見つけ、((OsCommPtr)(clients [i]- > 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
ソケットが見つかったら、そのソケットに接続しているユーザーを確認し、最終的にプロセスを見つけることができます。
警告:Xサーバー内からgサーバーをXサーバーに接続しないでください。gdbは接続先のプロセスを一時停止するため、Xセッション内から接続すると、Xサーバーがフリーズし、gdbとやり取りできなくなります。テキスト端末(Ctrl+Alt+F2
)に切り替えるか、ssh経由でマシンに接続する必要があります。
例:
XサーバーのPIDを見つけます。
$ ps ax | grep X
1237 tty1 Ssl+ 11:36 /usr/bin/X :0 vt1 -nr -nolisten tcp -auth /var/run/kdm/A:0-h6syCa
ウィンドウIDは0x1600045であるため、クライアントベースは0x1600000です。Xサーバーに接続し、そのクライアントベースのクライアントソケット記述子を見つけます。Xサーバーのデバッグ情報をインストールする必要があります(rpmディストリビューションの場合は-debuginfoパッケージ、debの場合は-dbgパッケージ)。
$ 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
それでおしまい。そのウィンドウを保持するプロセスは、プロセスID 7725の「firefox」です。
2017編集:このunix socketpairのもう一方の端は誰ですか?。Linux 3.3以降およびlsof
4.89以降では、上記の3〜5を次のように置き換えることができます。
lsof +E -a -p 1237 -d 31
ID 1237のXサーバープロセスのfd 31のソケットの反対側にいるのは誰かを見つけるため。