이 X11 창은 어떤 프로세스입니까? 항상 가능하지는

X11 창 ID가 주어지면 창을 만든 프로세스의 ID를 찾는 방법이 있습니까?

예를 들어, 창이 TCP 연결을 통해 온 경우와 같이 항상 가능하지는 않습니다. 이 경우 원격 끝과 관련된 IP 및 포트를 원합니다.

이 질문은 이전에 Stack Overflow 에서 요청되었으며 제안 된 방법은 _NET_WM_PID속성 을 사용하는 것 입니다. 그러나 그것은 응용 프로그램에 의해 설정됩니다. 응용 프로그램이 잘 재생되지 않으면 어떻게 할 수 있습니까?



답변

당신의 X 서버가 지원하지 않는 한 XResQueryClientIds에서 X-자원 1.2 확장 나는 더 모르는 쉽게 하는 방법 안정적으로 프로세스 ID를 요청합니다. 그러나 다른 방법이 있습니다.

창문이 있고 아직 ID를 모르는 경우 쉽게 찾을 수 있습니다. 문제의 창 옆에있는 터미널을 열고 실행 한 다음 해당 창을 xwininfo클릭하십시오. xwininfowindow-id를 보여줍니다.

따라서 0x1600045와 같은 창 ID를 알고 있고 그것을 소유하는 프로세스가 무엇인지 찾고 싶다고 가정 해 봅시다.

해당 윈도우가 누구인지 확인하는 가장 쉬운 방법은 XKillClient를 실행하는 것입니다.

xkill -id 0x1600045

어떤 프로세스가 막 죽었는지 확인하십시오. 그러나 물론 그것을 죽이는 것이 마음에 들지 않는 경우에만!

쉽고 신뢰할 수없는 또 다른 방법은 해당 속성 _NET_WM_PIDWM_CLIENT_MACHINE속성 을 확인하는 것입니다 .

xprop -id 0x1600045

그것이 도구가 좋아 xlsclients하고하는 xrestop일입니다.

불행히도이 정보는 프로세스가 악하고 변경 되었기 때문에뿐만 아니라 버그이기 때문에 부정확 할 수 있습니다. 예를 들어 파이어 폭스 충돌 / 다시 시작 후 _NET_WM_PID오래 전에 죽은 프로세스 를 가리키는 고아 창 (플래시 플러그인에서)을 보았습니다 .

다른 방법은 달리는 것입니다

xwininfo -root -tree

해당 창의 부모 속성을 확인하십시오. 또한 창 원점에 대한 힌트를 줄 수도 있습니다.

그러나! 해당 프로세스가 해당 창을 생성 한 프로세스를 찾을 수 없지만 해당 프로세스가 X 서버에 연결된 위치를 찾는 방법은 여전히 ​​있습니다. 그리고 그 방법은 실제 해커를위한 것입니다. 🙂

하위 비트가 0 인 0x1600000과 같은 창 ID 0x1600045는 “클라이언트 기반”입니다. 그리고 해당 클라이언트에 할당 된 모든 자원 ID는 “기반”(0x1600001, 0x1600002, 0x1600003 등)입니다. X 서버는 클라이언트에 대한 정보를 clients [] 배열에 저장하고 각 클라이언트의 “기본”은 clients [i]-> clientAsMask 변수에 저장됩니다. 해당 클라이언트에 해당하는 X- 소켓을 찾으려면을 사용하여 X-server에 연결하고 gdbclients [] 배열을 살펴보고 해당 클라이언트를 찾은 다음 clientAsMask소켓 설명자를 인쇄하여 ((OsCommPtr) (clients [i]- > osPrivate))-> fd.

많은 X- 클라이언트가 연결되어있을 수 있으므로 모든 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 서버에 설치된 디버그 정보가 필요합니다 (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
    

그게 다야. 해당 창을 유지하는 프로세스는 프로세스 ID 7725를 가진 “firefox”입니다.


2017 편집 : 이 유닉스 소켓 페어의 다른 쪽 끝은 누가 있습니까? 에서 더 많은 옵션 이 있습니다. . Linux 3.3 이상 및 lsof4.89 이상에서는 3에서 5까지의 포인트를 다음으로 바꿀 수 있습니다.

lsof +E -a -p 1237 -d 31

ID가 1237 인 X-server 프로세스의 fd 31에서 소켓의 다른 쪽 끝에있는 사람을 찾으십시오.


답변

xdotool이 작동하지 않았습니다. 이것은했다 :

운영

xprop _NET_WM_PID

창을 클릭하십시오.

이것은 http://www.linuxquestions.org/questions/linux-software-2/advanced-question-finding-pid-of-an-x-window-328983/ 의 답변을 기반으로합니다 .


답변

xdotool이 설치되어 있다면

xdotool selectwindow getwindowpid

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

(해당 창을 선택하는 다른 방법이 있습니다. 예를 들어, 창 ID가있는 경우에는 할 수 있습니다 xdotool getwindowpid <number>. 이름 또는 클래스 등으로 선택할 수도 있습니다.)

나는 이것이 WM을 대신하여 좋은 경기를해야한다고 생각합니다. 나는 많이 실험하지 않았거나 필요했습니다.


답변

_NET_WM_PID(그것이 알고 얼마나 또 다른 X11 클라이언트로?) 윈도우 관리자에 의해 설정되어 있지 않습니다.

대신, 준수 X11 클라이언트 (응용 프로그램) 설정 것으로 예상된다 _NET_WM_PIDWM_CLIENT_MACHINE자신의 창에. 제대로 작동하는 응용 프로그램을 가정하면 창 관리자가 실행 중인지 여부에 관계없이 적용됩니다.

경우 WM_CLIENT_MACHINE자신의 호스트 이름입니다, 다음 PID는 의미가 있어야한다.
그렇지 않으면 “원격 연결과 관련된 IP 및 포트를 원합니다”— 이것이 무엇을 의미하는지 잘 모르겠습니다. 예를 들어 X 전달을 사용하여 ssh 세션을 연 경우 전달 된 앱에서 열린 창에는 원격 PID 및 호스트 이름이 표시되지만 해당 원격 호스트에 다시 연결할 수있는 방법은 없습니다.


답변

xdotoolUbuntu 11.04 베타 버전 을 사용할 수 있었지만 selectwindow유효한 명령이 아니기 때문에 스크립트를 해킹해야했습니다.

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

그런 다음 원하는 창을 선택하는 동안 창 ID가 지나가는 것을보고 책임있는 PID를 다음과 같이 디코딩하십시오.

$ xdotool getwindowpid <the-window-id>