X11ウィンドウIDが与えられた場合、それを作成したプロセスのIDを見つける方法はありますか?
もちろん、これが常に可能であるとは限りません。たとえば、ウィンドウがTCP接続を介して来た場合などです。その場合、リモートエンドに関連付けられたIPとポートが必要です。
以前にStackOverflowで質問があり、提案された方法は_NET_WM_PID
を使用することでした。 財産。しかし、それはアプリケーションによって設定されます。アプリケーションがうまく機能しない場合にそれを行う方法はありますか?
承認された回答:
XサーバーがXResQueryClientIds
をサポートしていない限り X-Resourcev1.2拡張機能から簡単はわかりません 確実にする方法 プロセスIDを要求します。ただし、他の方法もあります。
目の前に窓があり、そのIDがまだわからない場合は、簡単に見つけることができます。問題のウィンドウの横にあるターミナルを開き、xwininfo
を実行します。 そこで、そのウィンドウをクリックします。 xwininfo
window-idが表示されます。
したがって、ウィンドウIDを知っていると仮定しましょう。 0x1600045、そしてそれを所有しているプロセスが何であるかを見つけたい。
そのウィンドウが誰に属しているかを確認する最も簡単な方法は、そのウィンドウに対してXKillClientを実行することです。つまり:
xkill -id 0x1600045
そして、どのプロセスがちょうど死んだかを見てください。ただし、もちろん殺してもかまわない場合に限ります!
もう1つの簡単ですが信頼性の低い方法は、その_NET_WM_PID
を確認することです。 およびWM_CLIENT_MACHINE
プロパティ:
xprop -id 0x1600045
それがxlsclients
のようなツールです およびxrestop
します。
残念ながら、この情報は、プロセスが悪で変更されただけでなく、バグがあったために正しくない可能性があります。たとえば、Firefoxのクラッシュ/再起動後、_NET_WM_PID
の孤立したウィンドウ(フラッシュプラグインから)が表示されました。 ずっと前に死んだプロセスを指しています。
別の方法は実行することです
xwininfo -root -tree
問題のウィンドウの親のプロパティを確認します。それはまたあなたに窓の起源についてのいくつかのヒントを与えるかもしれません。
だが!どのプロセスがそのウィンドウを作成したかがわからない場合でも、そのプロセスがXサーバーに接続している場所を見つける方法はあります。そして、その方法は本当のハッカーのためのものです。 🙂
下位ビットがゼロになっていることがわかっているwindow-id0x1600045(つまり、0x1600000)は、「クライアントベース」です。そして、そのクライアントに割り当てられたすべてのリソースIDは、それに「基づいています」(0x1600001、0x1600002、0x1600003など)。 Xサーバーはクライアントに関する情報をclients[]配列に格納し、クライアントごとにその「ベース」はclients[i]->clientAsMask変数に格納されます。そのクライアントに対応するXソケットを見つけるには、gdb
を使用してXサーバーに接続する必要があります。 、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
ソケットを見つけたら、誰がソケットに接続しているかを確認し、最終的にプロセスを見つけることができます。
関連:Windows 10ストアからサイドローディングするアプリをダウンロードするにはどうすればよいですか?
警告 :Xサーバー内からXサーバーにgdbを接続しないでください。 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-distributionsの場合は-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
それでおしまい。そのウィンドウを維持するプロセスは、プロセスID7725の「Firefox」です
2017編集 :このUNIXソケットペアのもう一方の端を持っているのは誰ですか?に見られるように、現在、より多くのオプションがあります。 Linux3.3以降およびlsof
の場合 4.89以上の場合、上記のポイント3から5を次のように置き換えることができます。
lsof +E -a -p 1237 -d 31
ID1237のX-serverプロセスのfd31のソケットのもう一方の端にいる人を見つけるため。