이 X11 창을 만든 프로세스는 무엇입니까?

이 X11 창을 만든 프로세스는 무엇입니까?

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간단하지만 신뢰할 수 없는 또 다른 방법은 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, client[] 배열을 반복하고, 해당 배열을 사용하여 클라이언트를 찾고, 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를 통해 컴퓨터에 연결해야 합니다.

예:

  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-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
    
  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프로세스를 찾을 수 있습니다. 그러나 위에 표시된 것처럼 유닉스 소켓이 표시될 가능성이 높으며 이는 로컬 클라이언트임을 의미합니다.

  4. 이 유닉스 소켓에 대한 쌍을 찾으려면 다음을 사용할 수 있습니다.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
    

그게 다야. 이 창을 보유한 프로세스는 "firefox"이고 프로세스 ID는 7725입니다.


2017년 편집: 이제 아래와 같이 더 많은 옵션이 있습니다.이 유닉스 소켓 쌍의 반대쪽 끝을 갖고 있는 사람이 있나요?. Linux 3.3 이상 및 lsof4.89 이상의 경우 위의 3~5번 항목을 다음으로 바꿀 수 있습니다.

lsof +E -a -p 1237 -d 31

ID가 1237인 X 서버 프로세스의 fd 31 소켓 반대편에 누가 있는지 알아보세요.

답변2

xdotool나에게 적합하지 않습니다. 이렇게 했습니다:

달리기

xprop _NET_WM_PID

그리고 창을 클릭해주세요.

이는 다음을 기반으로 합니다.Linux 문제에서 X 창의 PID 찾기.

답변3

당신이 가지고 있다면xdo 도구그럼 설치가 완료되었습니다

xdotool selectwindow getwindowpid

그런 다음 해당 창을 클릭하면 PID가 반환됩니다.

(관련 창을 선택하는 다른 방법이 있습니다. 예를 들어 해당 창 ID가 있으면 그렇게 할 수 있습니다 xdotool getwindowpid <number>. 이름이나 클래스 등으로 선택할 수도 있습니다.)

나는 이것이 WM이 잘 수행되어야 한다고 생각한다. 실험을 많이 해보지도 않았고, 실험을 많이 할 필요도 없어요.

답변4

xdotoolUbuntu 11.04 베타에서 작동하게 할 수 있었지만 이것은 selectwindow유효한 명령이 아니었고 다음을 사용하여 스크립트를 해킹해야 했습니다.

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

그런 다음 원하는 창이 선택되면 창 ID를 확인하고 다음을 사용하여 담당 PID를 디코딩합니다.

$ xdotool getwindowpid <the-window-id>

관련 정보