X11 창 ID가 주어지면 창을 만든 프로세스의 ID를 찾는 방법이 있습니까?
예를 들어, 창이 TCP 연결을 통해 온 경우와 같이 항상 가능하지는 않습니다. 이 경우 원격 끝과 관련된 IP 및 포트를 원합니다.
이 질문은 이전에 Stack Overflow 에서 요청되었으며 제안 된 방법은 _NET_WM_PID
속성 을 사용하는 것 입니다. 그러나 그것은 응용 프로그램에 의해 설정됩니다. 응용 프로그램이 잘 재생되지 않으면 어떻게 할 수 있습니까?
답변
당신의 X 서버가 지원하지 않는 한 XResQueryClientIds
에서 X-자원 1.2 확장 나는 더 모르는 쉽게 하는 방법 안정적으로 프로세스 ID를 요청합니다. 그러나 다른 방법이 있습니다.
창문이 있고 아직 ID를 모르는 경우 쉽게 찾을 수 있습니다. 문제의 창 옆에있는 터미널을 열고 실행 한 다음 해당 창을 xwininfo
클릭하십시오. xwininfo
window-id를 보여줍니다.
따라서 0x1600045와 같은 창 ID를 알고 있고 그것을 소유하는 프로세스가 무엇인지 찾고 싶다고 가정 해 봅시다.
해당 윈도우가 누구인지 확인하는 가장 쉬운 방법은 XKillClient를 실행하는 것입니다.
xkill -id 0x1600045
어떤 프로세스가 막 죽었는지 확인하십시오. 그러나 물론 그것을 죽이는 것이 마음에 들지 않는 경우에만!
쉽고 신뢰할 수없는 또 다른 방법은 해당 속성 _NET_WM_PID
과 WM_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에 연결하고 gdb
clients [] 배열을 살펴보고 해당 클라이언트를 찾은 다음 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를 통해 시스템에 연결해야합니다.
예:
-
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 배포 용 -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
있음을 알 수 있으며 연결된 컴퓨터로 이동 하여 프로세스를 찾을 수 있습니다. 그러나 위의 그림과 같이 유닉스 소켓이 보일 것입니다. 이는 로컬 클라이언트임을 의미합니다. -
해당 유닉스 소켓에 대한 쌍을 찾으려면 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
그게 다야. 해당 창을 유지하는 프로세스는 프로세스 ID 7725를 가진 “firefox”입니다.
2017 편집 : 이 유닉스 소켓 페어의 다른 쪽 끝은 누가 있습니까? 에서 더 많은 옵션 이 있습니다. . Linux 3.3 이상 및 lsof
4.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_PID
및 WM_CLIENT_MACHINE
자신의 창에. 제대로 작동하는 응용 프로그램을 가정하면 창 관리자가 실행 중인지 여부에 관계없이 적용됩니다.
경우 WM_CLIENT_MACHINE
자신의 호스트 이름입니다, 다음 PID는 의미가 있어야한다.
그렇지 않으면 “원격 연결과 관련된 IP 및 포트를 원합니다”— 이것이 무엇을 의미하는지 잘 모르겠습니다. 예를 들어 X 전달을 사용하여 ssh 세션을 연 경우 전달 된 앱에서 열린 창에는 원격 PID 및 호스트 이름이 표시되지만 해당 원격 호스트에 다시 연결할 수있는 방법은 없습니다.
답변
xdotool
Ubuntu 11.04 베타 버전 을 사용할 수 있었지만 selectwindow
유효한 명령이 아니기 때문에 스크립트를 해킹해야했습니다.
$ while true; do sleep 1; xdotool getactivewindow; done
그런 다음 원하는 창을 선택하는 동안 창 ID가 지나가는 것을보고 책임있는 PID를 다음과 같이 디코딩하십시오.
$ xdotool getwindowpid <the-window-id>