Jak znaleźć drugi koniec połączenia gniazda unix?

44

Mam proces (dbus-daemon), który ma wiele otwartych połączeń przez gniazda UNIX. Jednym z tych połączeń jest fd # 36:

=$ ps uw -p 23284
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
depesz   23284  0.0  0.0  24680  1772 ?        Ss   15:25   0:00 /bin/dbus-daemon --fork --print-pid 5 --print-address 7 --session

=$ ls -l /proc/23284/fd/36 
lrwx------ 1 depesz depesz 64 2011-03-28 15:32 /proc/23284/fd/36 -> socket:[1013410]

=$ netstat -nxp | grep 1013410
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
unix  3      [ ]         STREAM     CONNECTED     1013410  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD

=$ netstat -nxp | grep dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1013953  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1013825  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1013726  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1013471  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1013410  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1012325  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1012302  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1012289  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1012151  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011957  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011937  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011900  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011775  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011771  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011769  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011766  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011663  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011635  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011627  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011540  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011480  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011349  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011312  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011284  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011250  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011231  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011155  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011061  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011049  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011035  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1011013  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1010961  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD
unix  3      [ ]         STREAM     CONNECTED     1010945  23284/dbus-daemon   @/tmp/dbus-3XDU4PYEzD

Na podstawie połączeń numerycznych zakładam, że dbus-daemon to tak naprawdę serwer. Co jest OK Ale jak mogę znaleźć, który proces jest z nim połączony - używając połączenia, które jest 36 uchwytem pliku w programie uruchamiającym dbus? Próbowałem lsof, a nawet greps na / proc / net / unix, ale nie mogę znaleźć sposobu na znalezienie procesu klienta.


źródło
Odpowiedź na to pytanie znajduje się w U&L: Kto ma drugi koniec tej pary gniazd unixowych?
sch

Odpowiedzi:

25

Całkiem niedawno natknąłem się na podobny problem. Byłem zszokowany, gdy dowiedziałem się, że istnieją przypadki, w których może to nie być możliwe. Odkopałem komentarz twórcy lsof (Vic Abell), w którym wskazał, że zależy to w dużej mierze od implementacji gniazd unixowych. Czasami dostępne są informacje o „punkcie końcowym” dla gniazda, a czasem nie. Niestety, jak podkreśla, w Linuksie jest to niemożliwe.

Na przykład w systemie Linux, gdzie lsof musi używać / proc / net / unix, wszystkie gniazda domeny UNIX mają powiązaną ścieżkę, ale nie zawierają informacji o punkcie końcowym. Często nie ma określonej ścieżki. To często uniemożliwia określenie drugiego punktu końcowego, ale jest to wynikiem wdrożenia systemu plików Linux / proc.

Jeśli spojrzysz na / proc / net / unix, zobaczysz na własne oczy, że (przynajmniej w moim systemie) ma absolutną rację. Nadal jestem w szoku, ponieważ uważam, że taka funkcja jest niezbędna podczas śledzenia problemów z serwerem.

Jacek Prucia
źródło
Zauważ, że /proc/net/unixPODDA Ci plik docelowy losowego odniesienia do gniazda domeny, z którego wykopałeś /proc/.../fd/.
i336_
26

Ta odpowiedź dotyczy tylko systemu Linux. Na podstawie odpowiedzi z Unix & Linux Stack Exchange udało mi się zidentyfikować drugi koniec gniazda domeny unix za pomocą wbudowanych struktur danych, do których można uzyskać dostęp za pomocą gdbi /proc/kcore. Musisz włączyć opcje CONFIG_DEBUG_INFOi CONFIG_PROC_KCOREjądra.

Możesz użyć, lsofaby uzyskać adres jądra gniazda, który przyjmuje postać wskaźnika, np 0xffff8803e256d9c0. Liczba ta jest w rzeczywistości adresem odpowiedniej struktury lub typu pamięci w jądrze struct unix_sock. Ta struktura ma pole o nazwie, peerktóre wskazuje na drugi koniec gniazda. Więc polecenia

# gdb /usr/src/linux/vmlinux /proc/kcore
(gdb) p ((struct unix_sock*)0xffff8803e256d9c0)->peer

wypisze adres drugiego końca połączenia. Możesz grepować wynik lsof -Udla tego numeru, aby zidentyfikować numer procesu i deskryptora pliku tego drugiego końca.

Niektóre dystrybucje wydają się zapewniać symbole debugowania jądra jako osobny pakiet, który zająłby miejsce vmlinuxpliku w powyższym poleceniu.

MvG
źródło
Wygląda to interesująco, ale wymóg ponownej kompilacji jądra wydaje się przesadą. Myślę, że być może byłoby to możliwe bez ręcznie wykonanego jądra i bez użycia gdb, po prostu zerkając na wartości w kcore i wykonując „ręczne” dekodowanie wartości.
3
@depesz, wszystko co musisz wiedzieć to przesunięcie peerelementu w unix_sockstrukturze. W moim systemie x86_64 to przesunięcie wynosi 656 bajtów, więc mógłbym uzyskać ten drugi koniec za pomocą p ((void**)0xffff8803e256d9c0)[0x52]. Oczywiście nadal potrzebujesz CONFIG_PROC_KCORE.
MvG
11

Właściwie ssod iproute2(zamiennik netstat, ifconfig itp.) Może pokazać te informacje.

Oto przykład pokazujący gniazdo domeny unix ssh-agent, z którym sshpołączony jest proces:

$ sudo ss -a --unix -p
Netid  State      Recv-Q Send-Q Local                             Address:Port          Peer    Address:Port
u_str  ESTAB      0      0      /tmp/ssh-XxnMh2MdLBxo/agent.27402 651026                *       651642                users:(("ssh-agent",pid=27403,fd=4)
u_str  ESTAB      0      0       *                                651642                *       651026                users:(("ssh",pid=2019,fd=4))
Zulakis
źródło
Hmm Ciekawe ... Przegapiłem, że kolumny „Adres: Port” można dopasować, nawet jeśli kolumna „Peer” jest całkowicie bezużyteczna dla gniazd domeny unix.
SamB
9

Gniazdom uniksowym zwykle przypisuje się numery parami i zwykle następują one po sobie. Więc dla ciebie para prawdopodobnie wynosiłaby 1013410 +/- 1. Zobacz, który z nich istnieje i zgadnij, kto jest winowajcą.

Devdas
źródło
8

Napisałem narzędzie, które wykorzystuje metodę gdb MvG, aby niezawodnie uzyskać informacje o gniazdach, symbole debugowania jądra nie są potrzebne.

Aby połączyć proces z danym gniazdem, przekaż mu numer i-węzła:

# socket_peer 1013410
3703 thunderbird 

Aby dowiedzieć się o wszystkich procesach jednocześnie netstat_unix, dodaje kolumnę do danych wyjściowych netstat:

# netstat_unix
Proto RefCnt Flags       Type       State         I-Node   PID/Program name     Peer PID/Program name  Path
unix  3      [ ]         STREAM     CONNECTED     6825     982/Xorg             1497/compiz            /tmp/.X11-unix/X0
unix  3      [ ]         STREAM     CONNECTED     6824     1497/compiz          982/Xorg                 
unix  3      [ ]         SEQPACKET  CONNECTED     207142   3770/chromium-brows  17783/UMA-Session-R       
unix  3      [ ]         STREAM     CONNECTED     204903   1523/pulseaudio      3703/thunderbird       
unix  3      [ ]         STREAM     CONNECTED     204902   3703/thunderbird     1523/pulseaudio           
unix  3      [ ]         STREAM     CONNECTED     204666   1523/pulseaudio      3703/thunderbird       
...

Spróbuj, netstat_unix --dumpjeśli potrzebujesz wyników, które można łatwo przeanalizować.
Szczegółowe informacje można znaleźć na stronie https://github.com/lemonsqueeze/unix_sockets_peers .

Dla informacji, włamanie i-węzła + 1 / -1 nie jest niezawodne. Działa przez większość czasu, ale zawiedzie lub (gorzej) zwróci niewłaściwe gniazdo, jeśli nie będziesz miał szczęścia.

lemonsqueeze
źródło
1

Edytuj swój system.conf

W tym pliku możesz dodać więcej rzeczy do celów debugowania.

Lokalizacja pliku: /etc/dbus-1/system.conf

W celu debugowania możesz edytować plik system.conf, aby umożliwić podsłuch:

  1. zastąp sekcję zasad przez:

    <policy context="default">

    <!-- Allow everything to be sent -->

    <allow send_destination="*" eavesdrop="true"/>

    <!-- Allow everything to be received -->

    <allow eavesdrop="true"/>

    <!-- Allow anyone to own anything -->

    <allow own="*"/>

    <!-- XXX: Allow all users to connect -->

    <allow user="*"/> </policy>

  2. Usuń dołączony wiersz: system.d

    <includedir>system.d</includedir>

Źródło: http://old.nabble.com/dbus-send-error-td29893862.html


Kilka innych przydatnych rzeczy dotyczących gniazd unixowych

Najprostszym sposobem, aby dowiedzieć się, co dzieje się w autobusie, jest uruchomienie dbus-monitorprogramu, który jest dostarczany z pakietem D-Bus

Możesz także spróbować użyć dbus-cleanup-socketsdo czyszczenia resztek gniazd.

Poniższe polecenie pokaże, który proces jest podłączony ile razy do gniazd dbus na podstawie netstatdanych wyjściowych:

sudo netstat -nap | grep dbus | grep CONNECTED | awk '{print $8}' | sort | uniq -c

(testowany na Ubuntu)

Hardcorowy sposób: to polecenie ręcznie znajdzie procesy z / proc i pokaże, które używają najwięcej połączeń (wszystkie typy gniazd):

ls -lR */fd/* | grep socket | sed -r "s@([0-9{1}]+)/fd/@_\1_@g" | awk -F_ '{print $2}' | uniq -c | sort -n | awk '{print $1" "$2; print system("ps "$2"|tail -n1")}'

Przykładowe dane wyjściowe:

(liczba, PID, a następny wiersz zawiera szczegółowe informacje na temat procesu)

25 3732
 3732 ?        Ss     0:38 /usr/bin/wineserver
89 1970
 1970 ?        Ss     0:02 //bin/dbus-daemon --fork --print-pid 5 --print-address 7 --session

(testowany na Ubuntu)

Baw się dobrze.


Zobacz także powiązane artykuły w celach informacyjnych:

kenorb
źródło