Bu X11 penceresini hangi süreç yarattı?


75

X11 pencere kimliği verildiğinde, onu oluşturan işlemin kimliğini bulmanın bir yolu var mı?

Tabii ki bu her zaman mümkün değildir, örneğin pencerenin bir TCP bağlantısı üzerinden gelmesi durumunda. Bu durumda uzak uçla ilgili IP ve portu istiyorum.

Soru daha önce Yığın Taşması'nda sorulmuştu ve önerilen bir yöntem _NET_WM_PIDözelliği kullanmaktı . Ancak bu uygulama tarafından belirlenir. Uygulama güzel çalmıyorsa bunu yapmanın bir yolu var mı?


Yanıtlar:


60

X-sunucu destekliyorsa sürece XResQueryClientIdsgelen X-Kaynak v1.2 uzantısı hiçbir biliyorum kolay yol güvenilir bir süreç kimliği isteyin. Bununla birlikte başka yollar da var.

Önünüzde bir pencere varsa ve henüz kimliğini bilmiyorsanız, onu bulmak kolaydır. Sadece, söz konusu pencerenin yanındaki bir terminali açın, xwininfoorada çalıştırın ve o pencereye tıklayın. xwininfosize pencere kimliğini gösterecektir.

Öyleyse, bir pencere kimliği bildiğinizi varsayalım; örneğin, 0x1600045 ve bulmak istediğiniz, ona sahip olan sürecin ne olduğunu.

Bu pencerenin kime ait olduğunu kontrol etmenin en kolay yolu, bunun için XKillClient'i çalıştırmaktır:

xkill -id 0x1600045

ve hangi sürecin yeni öldüğünü görün. Ama sadece onu öldürmeyi sakıncası yoksa elbette!

Kolay ve güvenilmez bir başka yol da özelliklerini _NET_WM_PIDve WM_CLIENT_MACHINEözelliklerini kontrol etmektir :

xprop -id 0x1600045

Araçlar böyle yapar xlsclientsve xrestopyapar.

Ne yazık ki, bu bilgi yalnızca süreç kötüye gittiği ve bunları değiştirdiği için değil, aynı zamanda buggy nedeniyle de yanlış olabilir. Örneğin, bazı firefox çökmelerinden / yeniden başlattıktan sonra _NET_WM_PID, uzun zaman önce ölen bir sürece işaret eden artık pencereleri (flash eklentisinden sanırım) gördüm .

Alternatif yol çalıştırmaktır

xwininfo -root -tree

ve söz konusu pencerenin ebeveynlerinin özelliklerini kontrol edin. Bu ayrıca pencere kökenleri hakkında bazı ipuçları verebilir.

Fakat! Bu pencerede hangi işlemin yaratıldığını bulamıyor olsanız da, bu işlemin X-sunucusuna nereden bağlandığını bulmanın bir yolu var. Ve bu şekilde gerçek hackerlar için. :)

Alt bitlerle bildiğiniz pencere kimliği 0x1600045, sıfırlanmış (yani 0x1600000) bir "müşteri tabanı" dır. Ve bu müşteri için tahsis edilen tüm kaynak kimlikleri buna "dayanmaktadır" (0x1600001, 0x1600002, 0x1600003, vb.). X-server müşterileri hakkındaki bilgileri client [] dizisinde saklar ve her istemci için "base" client [i] -> clientAsMask değişkeninde saklanır. Bu müşteriye karşılık gelen X soketini bulmak için, X-sunucuya eklemeniz gdb, istemciler [] dizisinin üzerinden geçmeniz, bununla istemciyi bulmanız clientAsMaskve ((OsCommPtr) (istemciler [i) - içinde saklanan soket tanımlayıcısını yazdırmanız gerekir) > osPrivate)) -> fd.

Bağlı birçok X istemcisi olabilir, bu yüzden hepsini manuel olarak kontrol etmemek için bir gdb işlevi kullanalım:

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

Soketi bulduğunuzda, kimin bağlı olduğunu kontrol edebilir ve sonunda işlemi bulabilirsiniz.

UYARI : Gdb'yi X-sunucusuna INSIDE'dan X-server'a bağlamayın. gdb bağlı olduğu işlemi askıya alır, böylece X oturumunun içinden eklerseniz, X sunucunuzu dondurursunuz ve gdb ile etkileşime giremezsiniz. Metin terminaline ( Ctrl+Alt+F2) geçmeli veya ssh üzerinden makinenize bağlanmalısınız.

Örnek:

  1. X sunucunuzun PID'sini bulun:

    $ 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. Pencere kimliği 0x1600045, bu nedenle istemci tabanı 0x1600000. X sunucusuna ekleyin ve bu müşteri tabanı için istemci soketi tanımlayıcısını bulun. X sunucusu için hata ayıklama bilgisine ihtiyacınız olacak (rpm dağıtımları için -debugin paketi veya deb'ler için -dbg paketi).

    $ 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. Artık istemcinin bir sunucu soketine 31 bağlı olduğunu biliyorsunuz. Bu soketin lsofne olduğunu bulmak için kullanın :

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

    (burada "X", işlem adıdır, "1237", pid, "root", çalıştığı kullanıcı, "31u", soket tanımlayıcısıdır)

    Burada istemcinin TCP üzerinden bağlı olduğunu görebilir, daha sonra bağlı olduğu makineye gidebilir netstat -napve işlemi bulmak için orada kontrol edebilirsiniz . Fakat büyük olasılıkla yukarıda gösterildiği gibi orada bir unix soketi göreceksiniz, bu da yerel bir müşteri olduğu anlamına geliyor.

  4. Bu unix soketine bir çift bulmak için MvG'nin tekniğini kullanabilirsiniz (takılı çekirdeğiniz için hata ayıklama bilgisine de ihtiyacınız olacaktır):

    $ sudo gdb -c /proc/kcore
    (gdb) print ((struct unix_sock*)0xffff810008339340)->peer
    $1 = (struct sock *) 0xffff810008339600
    (gdb) quit
    
  5. Artık müşteri soketini bildiğinize göre, lsofonu tutan PID'yi bulmak için kullanın :

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

Bu kadar. Bu pencereyi tutan işlem 7725 işlem kimliğiyle "firefox" dur.


2017 Düzenleme : Şimdi bu görüldüğü gibi daha fazla seçenek var. . Linux 3.3 veya üzeri ve lsof4.89 veya üzeri ile, yukarıdaki 3 ila 5 arasındaki noktaları değiştirebilirsiniz:

lsof +E -a -p 1237 -d 31

Soketin diğer ucunda, X-server işleminin 31. kimliği ile kimliği bulmak için, ID 1237.


6
Unix ve Linux Stack Exchange'e Hoş Geldiniz! Bu soruya cevabınız mükemmel. Umarım daha fazla soruya cevap vermeye gelirsin.

36

xdotool benim için işe yaramadı. Bu yaptı:

Çalıştırmak

xprop _NET_WM_PID

ve pencereye tıklayın.

Bu, http://www.linuxquestions.org/questions/linux-software-2/advanced-question-finding-pid-of-an-x-window-328983/ adresindeki cevaba dayanmaktadır.


Iphone'umu takarken yanıt vermeyen bir pencere istemi getirdiğinde benim için çalışıyor.
modulitos

1
Bazen tamamen asılı olan evrim için kullanışlıdır. kill $(xprop _NET_WM_PID|cut -d " " -f 3)
Gabriel Devillers

Aradığım şey buydu, xkill akışı
Rombus

13

Eğer xdotool kurulu ise

xdotool selectwindow getwindowpid

Ardından, söz konusu pencereye tıklandığında PID döndürülür.

(Söz konusu pencereyi seçmenin başka yolları da vardır, örneğin, eğer kendi pencere kimliğine sahipseniz, sadece yapabilirsiniz xdotool getwindowpid <number>. Ayrıca isme veya sınıfa göre de seçebilirsiniz.)

Bunun WM adına bazılarının iyi oynamasını gerektirdiğini düşünüyorum. Çok fazla denemedim ya da buna ihtiyacım olmadı.


2
xdo_getwinprop(xdo, window, atom_NET_WM_PID, &nitems, &type, &size)⇒ sadece okumak için bir kabuk sarmalayıcı _NET_WM_PID(kullanışlı, ama istediğim şeyi değil).
Gilles

11

_NET_WM_PID(Bu nasıl tanımış sadece başka X11 istemcisi olarak?) Pencere yöneticisi tarafından ayarlanmaz.

Bunun yerine, uyumlu X11 istemcileri (uygulamaları) ayarlamak beklenir _NET_WM_PIDve WM_CLIENT_MACHINEkendi pencerelerde. İyi niyetli bir uygulama varsayalım, bu bir pencere yöneticisinin çalışıp çalışmadığı doğru olacaktır.

Eğer WM_CLIENT_MACHINEkendi ana makine adı, sonra PID anlamlı olmalıdır.
Aksi halde, "Uzak uçla ilişkilendirilmiş IP ve bağlantı noktasını istiyorum" - Bunun ne anlama geldiğinden emin değilim. Örneğin, X yönlendirme etkinleştirilmiş açık bir ssh oturumunuz varsa, iletilen uygulamalar tarafından açılan pencereler uzak PID ve ana bilgisayar adı ile işaretlenir, ancak bu uzak ana bilgisayara geri bağlanmanın hiçbir yolu yoktur.


2
_NET_WM_PIDuygulama tarafından ayarlanır: doğru, bu daha mantıklı! Ancak bu X11 protokolü değil, nispeten yeni FreeDesktop teknik özelliği.
Gilles

Ssh durumunda, X sunucusuna gelince, bu sshd işleminden yerel bir bağlantıdır. Gerçi _NET_WM_PIDuzak PID ve set gibi görünüyor WM_CLIENT_MACHINE(xterm'den ile test) uzaktan bağlantı.
Gilles

4

xdotoolUbuntu 11.04 beta altında kullanabildim , ancak selectwindowgeçerli bir komut değildi, bir senaryoyu kesmek zorunda kaldım:

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

sonra istediğim pencereyi seçerken pencerenin geçtiğini izledikten sonra sorumlu PID'nin kodunu çözdüm:

$ xdotool getwindowpid <the-window-id>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.