このX11ウィンドウを作成したプロセスは何ですか?


75

X11ウィンドウIDを指定すると、それを作成したプロセスのIDを見つける方法はありますか?

もちろん、これは常に可能とは限りません。たとえば、ウィンドウがTCP接続を介して来た場合などです。その場合、リモートエンドに関連付けられているIPとポートが必要です。

Stack Overflow以前に質問があり、提案された方法は_NET_WM_PIDプロパティを使用することでした。しかし、それはアプリケーションによって設定されます。アプリケーションがうまく動作しない場合、それを行う方法はありますか?


回答:


60

XサーバーXResQueryClientIdsX-Resource v1.2拡張機能をサポートしていない限り、プロセスID を確実に要求する簡単な方法はわかりません。ただし、他の方法もあります。

目の前にウィンドウがあり、そのIDがまだわからない場合は、簡単に見つけることができます。問題のウィンドウの横にあるターミナルを開き、xwininfoそこで実行して、そのウィンドウをクリックするだけです。xwininfowindow-idが表示されます。

したがって、0x1600045などのウィンドウIDを知っていて、それを所有しているプロセスを見つけたいとしましょう。

そのウィンドウが誰に属しているかを確認する最も簡単な方法は、そのためにXKillClientを実行することです:

xkill -id 0x1600045

どのプロセスが停止したかを確認します。ただし、もちろんそれを殺しても構わない場合のみです!

もう一つの簡単ですが、信頼性の低い方法は、そのチェックすることです_NET_WM_PIDし、WM_CLIENT_MACHINEプロパティを:

xprop -id 0x1600045

これは、ツールが好きなものだxlsclientsxrestop行います。

残念ながら、この情報は、プロセスが悪かったために変更されただけでなく、バ​​グがあるために間違っている可能性があります。たとえば、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経由でマシンに接続する必要があります。

例:

  1. 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
    
  2. ウィンドウ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
    
  3. これで、クライアントがサーバーソケット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ソケットが表示されます。これは、ローカルクライアントであることを意味しています。

  4. そのUNIXソケットのペアを見つけるには、MvGの手法を使用できます (インストールされているカーネルのデバッグ情報も必要です)。

    $ sudo gdb -c /proc/kcore
    (gdb) print ((struct unix_sock*)0xffff810008339340)->peer
    $1 = (struct sock *) 0xffff810008339600
    (gdb) quit
    
  5. クライアントソケットがわかったので、それを使用lsofしてPIDを見つけます。

    $ sudo lsof -n | grep 0xffff810008339600
    firefox  7725  username  146u   unix 0xffff810008339600       8512421 socket
    

それでおしまい。そのウィンドウを保持するプロセスは、プロセスID 7725の「firefox」です。


2017編集このunix socketpairのもう一方の端は誰ですか?。Linux 3.3以降およびlsof4.89以降では、上記の3〜5を次のように置き換えることができます。

lsof +E -a -p 1237 -d 31

ID 1237のXサーバープロセスのfd 31のソケットの反対側にいるのは誰かを見つけるため。


6
UnixおよびLinux Stack Exchangeを歓迎します!この質問に対するあなたの答えは素晴らしいです。もう一度質問に答えてください。

36

xdotoolは機能しませんでした。これは:

走る

xprop _NET_WM_PID

ウィンドウをクリックします。

これは、http://www.linuxquestions.org/questions/linux-software-2/advanced-question-finding-pid-of-an-x-window-328983/の回答に基づいています


Iphoneを接続すると、応答しないウィンドウプロンプトが表示されたときに機能します。
modulitos 14年

1
時々完全にハングする証拠に役立ちます。kill $(xprop _NET_WM_PID|cut -d " " -f 3)
ガブリエルデヴィラーズ

これが私が探していたものです、xkillフロー
Rombus

13

あなたはしている場合はxdotoolインストールし、その後、

xdotool selectwindow getwindowpid

続いて問題のウィンドウをクリックすると、PIDが返されます。

(問題のウィンドウを選択する方法は他にxdotool getwindowpid <number>もあります。たとえば、ウィンドウIDを持っている場合に実行できます。名前やクラスなどで選択することもできます。)

これにはWMに代わって良いプレイが必要だと思います。私はあまり実験していない、またはする必要はありません。


2
xdo_getwinprop(xdo, window, atom_NET_WM_PID, &nitems, &type, &size)⇒これは単に読み取るためのシェルラッパー_NET_WM_PIDです(有用ですが、私が求めたものではありません)。
ジル

11

_NET_WM_PID(どのようにそれは知っているだろう、ちょうど別のX11クライアントとして?)ウィンドウマネージャによって設定されていません。

代わりに、対応のX11クライアント(アプリケーション)を設定することが期待されている_NET_WM_PIDWM_CLIENT_MACHINE、自分の窓の上に。正常に動作するアプリケーションを想定すると、これはウィンドウマネージャーが実行されているかどうかに関係なく当てはまります。

場合はWM_CLIENT_MACHINE、独自のホスト名で、その後、PIDは有意義である必要があります。
それ以外の場合、「リモートエンドに関連付けられたIPとポートが欲しい」—それが何を意味するのかわからない。たとえば、X転送を有効にしてsshセッションを開いている場合、転送されたアプリによって開かれたウィンドウはリモートPIDとホスト名でマークされますが、必ずしもそのリモートホストに接続する方法はありません。


2
_NET_WM_PIDアプリケーションによって設定されます:正しい、それはもっと理にかなっています!しかし、それはX11プロトコルではなく、比較的最近のFreeDesktop仕様です。
ジル

sshの場合、Xサーバーに関する限り、これはsshdプロセスからのローカル接続です。けれどもは_NET_WM_PID、リモートPIDにして設定されているように見えるWM_CLIENT_MACHINE(xtermのでテスト済み)リモート接続に。
ジル

4

私はxdotoolUbuntu 11.04ベータ版の下で使用することができましたselectwindowが、有効なコマンドではなかったので、スクリプトを次のようにハックする必要がありました。

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

次に、必要なウィンドウを選択している間にウィンドウIDが通過するのを見てから、次のように責任のあるPIDをデコードしました。

$ xdotool getwindowpid <the-window-id>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.