Як знайти інший кінець з'єднання unix?


44

У мене є процес (dbus-демон), який має багато відкритого з'єднання через сокети UNIX. Одним із таких з'єднань є 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

Виходячи з числових з'єднань, я припускаю, що dbus-демон є насправді сервером. Що добре. Але як я можу знайти, який процес до нього пов'язаний - використовуючи з'єднання, яке є 36-ю ручкою файлів у dbus-пускачі? Спробував lsof і навіть greps on / proc / net / unix, але я не можу знайти спосіб знайти клієнтський процес.


На це відповідає відповідь U&L: Хто має інший кінець цього пакету Unix?
sch

Відповіді:


25

Зовсім недавно я натрапив на подібну проблему. Я був шокований, дізнавшись, що є випадки, коли це може бути неможливим. Я розкопав коментар від творця lsof (Вік Абел), де він зазначив, що це сильно залежить від реалізації unix socket. Іноді так звана інформація про кінцеву точку для сокета доступна, а іноді - ні. На жаль, в Linux це неможливо, як він вказує.

Наприклад, у Linux, де lsof повинен використовувати / proc / net / unix, усі сокети домену UNIX мають зв'язаний шлях, але немає інформації про кінцеві точки. Часто немає обмеженого шляху. Це часто унеможливлює визначення іншої кінцевої точки, але це результат реалізації файлової системи Linux / proc.

Якщо ви подивитесь на / proc / net / unix, то можете самі переконатися, що (принаймні в моїй системі) він абсолютно прав. Я все ще в шоці, тому що я вважаю таку особливість важливою під час відстеження проблем із сервером.



Зауважте, що /proc/net/unixВІН повідомить вам цільовий файл посилання на випадковий сокет домену, з якого ви викопали /proc/.../fd/.
i336_

26

Ця відповідь призначена лише для Linux. На підставі відповіді Unix & Linux Stack Exchange я успішно визначив інший кінець сокета домену Unix, використовуючи структури даних в ядрі, доступ до яких використовувався gdbта /proc/kcore. Потрібно ввімкнути параметри CONFIG_DEBUG_INFOі CONFIG_PROC_KCOREядра.

Ви можете використовувати lsofдля отримання адреси ядра сокета, яка має форму вказівника, наприклад 0xffff8803e256d9c0. Це число фактично є адресою відповідної структури або типу пам'яті в ядрі struct unix_sock. Ця структура має поле, peerяке називається на іншому кінці сокета. Отже команди

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

надрукує адресу іншого кінця з'єднання. Ви можете зібрати результат lsof -Uцього числа, щоб визначити номер дескриптора процесу та файлу цього іншого кінця.

Здається, деякі дистрибутиви надають символи налагодження ядра як окремий пакет, який би зайняв місце vmlinuxфайлу у наведеній вище команді.


Це виглядає цікаво, але вимога перекомпілювати ядро ​​здається зайвим. Я думаю, що, можливо, це вдасться зробити без ручного ядра та без використання gdb, просто зазирнути до значень у kcore і зробити якесь "ручне" розшифрування значень.

3
@depesz, все, що потрібно знати, - це зміщення peerчлена в unix_sockструктурі. У моїй системі x86_64 цей зсув становить 656 байт, тому я міг отримати інший кінець за допомогою p ((void**)0xffff8803e256d9c0)[0x52]. Вам все одно потрібно CONFIG_PROC_KCORE, очевидно.
MvG

11

Насправді, ssз iproute2(заміна netstat, ifconfig тощо) може відображатися ця інформація.

Ось приклад, що показує сокет домену ssh-agent unix, до якого підключено sshпроцес:

$ 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))

Хм. Цікаво ... Я пропустив, що стовпці "Адреса: Порт" можуть відповідати, навіть якщо стовпець "Peer" абсолютно непридатний для роз'ємів домену Unix.
СамБ

9

Розетки Unix зазвичай присвоюються числами парами і зазвичай є послідовними. Отже, пара для вас, ймовірно, буде 1013410 +/- 1. Подивіться, хто з цих двох існує, і вгадайте винуватця.


8

Я написав інструмент, який використовує метод gdb MvG для надійного отримання інформації про однорангову сокет, символи налагодження ядра не потрібні.

Щоб підключити процес до даного сокета, передайте йому номер inode:

# socket_peer 1013410
3703 thunderbird 

Щоб дізнатися про всі процеси, що використовуються одночасно netstat_unix, він додає стовпчик до виводу 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       
...

Спробуйте, netstat_unix --dumpякщо вам потрібен вихід, який легко проаналізувати.
Детальніше дивіться на https://github.com/lemonsqueeze/unix_sockets_peers .

Для інформації inode + 1 / -1 хак не є надійним. Він працює більшу частину часу, але вийде з ладу або (що ще гірше) поверне неправильну розетку, якщо вам не пощастить.


1

Відредагуйте system.conf

У цей файл ви можете додати більше матеріалів для налагодження.

Розташування файлу: /etc/dbus-1/system.conf

Для налагодження ви можете відредагувати system.conf, щоб дозволити підслуховування:

  1. замініть розділ політики на:

    <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. Видаліть рядок включеного: system.d

    <includedir>system.d</includedir>

Джерело: http://old.nabble.com/dbus-send-error-td29893862.html


Ще деякі корисні речі, що стосуються unix-розеток

Найпростіший спосіб з’ясувати, що відбувається в шині - це запустити dbus-monitorпрограму, яка постачається з пакетом D-Bus

Також ви можете спробувати використовувати dbus-cleanup-socketsдля очищення залишки розеток.

Наступна команда покаже, який процес підключений скільки разів до dbus-сокетів на основі netstatвиводу:

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

(перевірено на Ubuntu)

Хардкор спосіб: Ця команда знайде вручну процеси з / proc і покаже, які використовують найбільш підключення (усі типи сокетів):

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")}'

Приклад виводу:

(count, PID і наступний рядок містить інформацію про процес)

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

(перевірено на Ubuntu)

Весело.


Дивіться також пов’язані статті для довідки:

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.