이 X11 창은 어떤 프로세스입니까?


75

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

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

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


답변:


60

당신의 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에서 소켓의 다른 쪽 끝에있는 사람을 찾으십시오.


6
유닉스 및 리눅스 스택 교환을 환영합니다! 이 질문에 대한 당신의 대답은 훌륭합니다. 더 많은 질문에 답하기 위해 다시 오시기 바랍니다.

36

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

운영

xprop _NET_WM_PID

창을 클릭하십시오.

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


아이폰을 연결하면 응답하지 않는 창 프롬프트가 나타납니다.
modulitos

1
때때로 완전히 끊어 졌음을 증명하는 데 유용합니다. kill $(xprop _NET_WM_PID|cut -d " " -f 3)
Gabriel Devillers

이것이 내가 찾던 것, xkill flow
Rombus

13

xdotool이 설치되어 있다면

xdotool selectwindow getwindowpid

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

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

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


2
xdo_getwinprop(xdo, window, atom_NET_WM_PID, &nitems, &type, &size)⇒ 읽을 수있는 쉘 래퍼 일뿐입니다 _NET_WM_PID(유용하지만 요청한 내용은 아님).
Gilles

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 사양입니다.
Gilles

ssh의 경우 X 서버와 관련하여 sshd 프로세스의 로컬 연결입니다. 비록 _NET_WM_PID원격 PID로 설정하고있는 것 같다 WM_CLIENT_MACHINE(xterm 등 테스트) 원격 연결에.
Gilles

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.