X11ウィンドウIDが与えられたら、それを生成したプロセスのIDを見つける方法はありますか?
もちろん、これは常に可能なわけではありません。たとえば、ウィンドウがTCP接続から出る場合です。この場合、リモート側に接続されたIPとポートが必要です。
この質問は、以前Stack Overflowで質問されたことがあります。で推奨されるアプローチは、この_NET_WM_PID
プロパティを使用することです。ただし、これはアプリケーションによって設定されます。アプリケーションが正しく実行されていない場合にこれを行う方法はありますか?
ベストアンサー1
XサーバーがXResQueryClientIds
サポートしていない限りX-リソース v1.2 拡張わからないシンプル続く安定してプロセスIDを要求しています。しかし、他の方法もあります。
前にウィンドウだけがまだIDがわからない場合は、見つけるのは簡単です。問題のあるウィンドウの横にある端末を開き、端末を起動してxwininfo
ウィンドウをクリックします。xwininfo
ウィンドウIDが表示されます。
したがって、0x1600045というウィンドウIDを知っていて、それを所有するプロセスを探したいとしましょう。
ウィンドウが誰に属しているかを確認する最も簡単な方法は、XKillClientを実行することです。例:
xkill -id 0x1600045
どのプロセスが終了したかを確認してください。でももちろん殺すのが気に入らない場合のみ!
_NET_WM_PID
単純だが信頼できないもう1つの方法は、sum属性を確認することですWM_CLIENT_MACHINE
。
xprop -id 0x1600045
それがまさにツールxlsclients
のようなものです。xrestop
する。
残念ながら、この情報は不正確かもしれません。プロセスが邪悪でそれを変更するだけでなく、エラーがあるからです。たとえば、いくつかのFirefoxがクラッシュ/再起動した後、ずっと前に死んだ_NET_WM_PID
プロセスを指す孤立したウィンドウ(フラッシュプラグインからのようです)を見ました。
もう一つの方法は走ることです。
xwininfo -root -tree
そして、そのウィンドウの親ウィンドウのプロパティを確認してください。また、ウィンドウのソースに関するいくつかのヒントを提供することもできます。
しかし!どのプロセスがウィンドウを作成したかを見つけることができないかもしれませんが、プロセスがどこでXサーバーに接続しているかを見つける方法があります。この方法は実際のハッカーに適しています。 :)
低いビットがクリアされた(例:0x1600000)、ウィンドウID 0x1600045として知られているのは「クライアントベース」です。このクライアントに割り当てられたすべてのリソースIDはこれを「ベース」にします(0x1600001、0x1600002、0x1600003など)。 Xサーバーはクライアントに関する情報をclient []配列に格納し、各クライアントの「デフォルト」はclient [i] -> clientAsMask変数に保存されます。そのクライアントに対応するXソケットを見つけるには、X-serverへの接続を使用し、gdb
クライアント[]配列を繰り返し、その配列を使用してクライアントを探し、clientAsMask
((OsCommPtr)(クライアントに格納されているソケット記述子を印刷する必要があります) . [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サーバー内でgdbを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-serverのデバッグ情報をインストールする必要があります(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
それはすべてです。このウィンドウを保持するプロセスは「firefox」で、プロセスIDは7725です。
2017年編集:これで、以下のように多くのオプションがあります。このUnixソケットペアの反対側の端を持っている人はいますか?。 Linux 3.3以降およびlsof
4.89以降の場合は、上記の3〜5番目の項目を次のように置き換えることができます。
lsof +E -a -p 1237 -d 31
IDが1237のXサーバープロセスのfd 31ソケットの反対側に誰がいるかを確認してください。