Quá trình nào tạo ra cửa sổ X11 này?


75

Đưa ra một ID cửa sổ X11, có cách nào để tìm ID của quá trình tạo ra nó không?

Tất nhiên điều này không phải lúc nào cũng có thể, ví dụ nếu cửa sổ đi qua kết nối TCP. Trong trường hợp đó, tôi muốn IP và cổng được liên kết với đầu cuối từ xa.

Câu hỏi đã được hỏi trước đó trên Stack Overflow và một phương pháp được đề xuất là sử dụng thuộc _NET_WM_PIDtính. Nhưng đó là thiết lập của ứng dụng. Có cách nào để làm điều đó nếu ứng dụng không chơi tốt không?


Câu trả lời:


60

Trừ khi máy chủ X của bạn hỗ trợ XResQueryClientIdstừ tiện ích mở rộng X-Resource v1.2, tôi không biết cách dễ dàng để yêu cầu ID tiến trình đáng tin cậy . Tuy nhiên, có nhiều cách khác.

Nếu bạn chỉ có một cửa sổ trước mặt và chưa biết ID của nó - thật dễ dàng để tìm ra nó. Chỉ cần mở một thiết bị đầu cuối bên cạnh cửa sổ trong câu hỏi, chạy xwininfoở đó và bấm vào cửa sổ đó. xwininfosẽ hiển thị cho bạn id cửa sổ.

Vì vậy, giả sử bạn biết một id cửa sổ, ví dụ 0x1600045 và muốn tìm, quá trình sở hữu nó là gì.

Cách dễ nhất để kiểm tra cửa sổ đó thuộc về ai là chạy XKillClient cho nó, tức là:

xkill -id 0x1600045

và xem quá trình nào vừa chết. Nhưng chỉ khi bạn không phiền giết nó tất nhiên!

Một cách dễ dàng nhưng không đáng tin cậy khác là kiểm tra thuộc tính _NET_WM_PIDWM_CLIENT_MACHINEthuộc tính của nó :

xprop -id 0x1600045

Đó là những gì công cụ thích xlsclientsxrestoplàm.

Thật không may, thông tin này có thể không chính xác không chỉ bởi vì quá trình này là xấu xa và thay đổi chúng, mà còn bởi vì nó là lỗi. Ví dụ: sau một số sự cố / khởi động lại firefox tôi đã thấy các cửa sổ mồ côi (từ plugin flash, tôi đoán vậy) với việc _NET_WM_PIDchỉ ra một quy trình, đã chết từ lâu.

Cách khác là chạy

xwininfo -root -tree

và kiểm tra thuộc tính của cha mẹ của cửa sổ trong câu hỏi. Điều đó cũng có thể cung cấp cho bạn một số gợi ý về nguồn gốc cửa sổ.

Nhưng! Mặc dù bạn có thể không tìm thấy quy trình nào đã tạo ra cửa sổ đó, nhưng vẫn có cách để tìm quá trình đó đã kết nối với máy chủ X từ đâu. Và cách đó là dành cho tin tặc thực sự. :)

Id cửa sổ 0x1600045 mà bạn biết với các bit thấp hơn bằng 0 (tức là 0x1600000) là "cơ sở khách". Và tất cả các ID tài nguyên, được phân bổ cho máy khách đó đều "dựa" vào nó (0x1600001, 0x1600002, 0x1600003, v.v.). Máy chủ X lưu trữ thông tin về các máy khách của nó trong mảng máy khách [] và đối với mỗi máy khách, "cơ sở" của nó được lưu trữ trong các máy khách [i] -> biến clientAsMask. Để tìm ổ cắm X, tương ứng với máy khách đó, bạn cần phải gắn vào máy chủ X với gdb, đi qua mảng máy khách [], tìm máy khách với đó clientAsMaskvà in mô tả ổ cắm của nó, được lưu trữ trong ((OsCommPtr) (máy khách [i] - > osPrivate)) -> fd.

Có thể có nhiều máy khách X được kết nối, vì vậy để không kiểm tra tất cả chúng theo cách thủ công, hãy sử dụng hàm 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

Khi bạn tìm thấy ổ cắm, bạn có thể kiểm tra xem ai đã kết nối với nó và cuối cùng tìm thấy quy trình.

CẢNH BÁO : KHÔNG đính kèm gdb với máy chủ X từ bên trong máy chủ X. gdb tạm dừng quá trình mà nó gắn vào, vì vậy nếu bạn đính kèm vào đó từ bên trong phiên X, bạn sẽ đóng băng máy chủ X của mình và sẽ không thể tương tác với gdb. Bạn phải chuyển sang thiết bị đầu cuối văn bản ( Ctrl+Alt+F2) hoặc kết nối với máy của bạn qua ssh.

Thí dụ:

  1. Tìm PID của máy chủ X của bạn:

    $ 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 cửa sổ là 0x1600045, vì vậy cơ sở khách hàng là 0x1600000. Đính kèm với máy chủ X và tìm mô tả ổ cắm máy khách cho cơ sở khách đó. Bạn sẽ cần thông tin gỡ lỗi được cài đặt cho máy chủ X (gói -debuginfo cho phân phối vòng / phút hoặc gói -dbg cho deb ').

    $ 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. Bây giờ bạn biết rằng máy khách được kết nối với ổ cắm máy chủ 31. Sử dụng lsofđể tìm ổ cắm đó là gì:

    $ sudo lsof -n | grep 1237 | grep 31
    X        1237    root   31u   unix 0xffff810008339340       8512422 socket
    

    (ở đây "X" là tên quy trình, "1237" là pid của nó, "root" là người dùng mà nó đang chạy, "31u" là một mô tả ổ cắm)

    Ở đó bạn có thể thấy rằng máy khách được kết nối qua TCP, sau đó bạn có thể đi đến máy được kết nối từ đó và kiểm tra netstat -naptại đó để tìm quy trình. Nhưng rất có thể bạn sẽ thấy một ổ cắm unix ở đó, như được hiển thị ở trên, có nghĩa là nó là một máy khách cục bộ.

  4. Để tìm một cặp cho ổ cắm unix đó, bạn có thể sử dụng kỹ thuật của MvG (bạn cũng sẽ cần thông tin gỡ lỗi cho kernel đã cài đặt):

    $ sudo gdb -c /proc/kcore
    (gdb) print ((struct unix_sock*)0xffff810008339340)->peer
    $1 = (struct sock *) 0xffff810008339600
    (gdb) quit
    
  5. Bây giờ bạn đã biết ổ cắm máy khách, hãy sử dụng lsofđể tìm PID giữ nó:

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

Đó là nó. Quá trình giữ cửa sổ đó là "firefox" với process-id 7725


Chỉnh sửa 2017 : Hiện tại có nhiều tùy chọn hơn như đã thấy tại Ai có đầu kia của sự thất bại unix này? . Với Linux 3.3 trở lên và bằng lsof4.89 trở lên, bạn có thể thay thế các điểm từ 3 đến 5 ở trên bằng:

lsof +E -a -p 1237 -d 31

để tìm ra ai ở đầu kia của ổ cắm trên fd 31 của quy trình máy chủ X có ID 1237.


6
Chào mừng đến với Sàn giao dịch ngăn xếp Unix và Linux! Câu trả lời của bạn cho câu hỏi này là tuyệt vời. Tôi hy vọng bạn trở lại để trả lời nhiều câu hỏi hơn.

36

xdotool không làm việc cho tôi. Điều này đã làm:

Chạy

xprop _NET_WM_PID

và bấm vào cửa sổ.

Điều này dựa trên câu trả lời tại http://www.linuxquestions.org/questions/linux-software-2/advified-question-finding-pid-of-an-x-window-328983/


Hoạt động với tôi khi cắm vào Iphone của tôi đưa ra lời nhắc cửa sổ không phản hồi.
modulitos

1
Hữu ích cho việc chứng minh rằng đôi khi treo hoàn toàn. kill $(xprop _NET_WM_PID|cut -d " " -f 3)
Gabriel Devillers

Đây là những gì tôi đang tìm kiếm, xkill Flow
Rombus

13

Nếu bạn đã cài đặt xdotool , thì

xdotool selectwindow getwindowpid

tiếp theo là nhấp vào cửa sổ trong câu hỏi sẽ trả về PID.

(Có nhiều cách khác để chọn cửa sổ đang đề cập, ví dụ: nếu bạn có ID cửa sổ của nó, bạn chỉ có thể làm xdotool getwindowpid <number>. Bạn cũng có thể chọn theo tên hoặc lớp, v.v.)

Tôi nghĩ rằng điều này đòi hỏi một số người chơi tốt thay mặt cho WM. Tôi chưa thử nghiệm nhiều, hoặc cần thiết.


2
xdo_getwinprop(xdo, window, atom_NET_WM_PID, &nitems, &type, &size)Nó chỉ là một trình bao bọc để đọc _NET_WM_PID(hữu ích, nhưng không phải là những gì tôi yêu cầu).
Gilles

11

Trình _NET_WM_PIDquản lý cửa sổ không được đặt (như chỉ là một ứng dụng khách X11 khác, làm sao nó biết được?).

Thay vào đó, các máy khách X11 (ứng dụng) tương thích dự kiến ​​sẽ được đặt _NET_WM_PIDWM_CLIENT_MACHINEtrên các cửa sổ riêng của chúng. Giả sử một ứng dụng hoạt động tốt, điều này sẽ đúng cho dù trình quản lý cửa sổ có chạy hay không.

Nếu WM_CLIENT_MACHINElà tên máy chủ của riêng bạn, thì PID phải có ý nghĩa.
Mặt khác, "Tôi muốn IP và cổng được liên kết với đầu cuối từ xa" - Tôi không chắc điều đó có nghĩa là gì. Ví dụ: nếu bạn có phiên ssh mở khi bật chuyển tiếp X, các cửa sổ được mở bởi các ứng dụng được chuyển tiếp sẽ được đánh dấu bằng PID và tên máy chủ từ xa, nhưng bạn không nhất thiết phải có bất kỳ cách nào để kết nối lại với máy chủ từ xa đó.


2
_NET_WM_PIDđược thiết lập bởi ứng dụng: đúng, điều đó có ý nghĩa hơn! Nhưng nó không phải là giao thức X11, đây là thông số kỹ thuật FreeDesktop tương đối gần đây .
Gilles

Trong trường hợp ssh, theo như máy chủ X có liên quan, đây là kết nối cục bộ từ quá trình sshd. Mặc dù _NET_WM_PIDdường như được đặt thành PID từ xa và WM_CLIENT_MACHINEkết nối từ xa (được thử nghiệm với xterm).
Gilles

4

Tôi đã có thể sử dụng bản xdotoolUbuntu 11.04 beta, nhưng selectwindowkhông phải là một lệnh hợp lệ, tôi đã phải hack một đoạn script với:

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

sau đó xem ID cửa sổ đi trong khi tôi chọn cửa sổ tôi muốn, sau đó giải mã PID có trách nhiệm với:

$ xdotool getwindowpid <the-window-id>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.