如何找到unix socket连接的另一端?

45 linux unix netstat socket dbus

我有一个进程(dbus-daemon),它通过 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
Run Code Online (Sandbox Code Playgroud)

根据连接数,我假设 dbus-daemon 实际上是服务器。这是好的。但是如何找到连接到它的进程 - 使用 dbus-launcher 中第 36 个文件句柄的连接?在 /proc/net/unix 上尝试了 lsof 甚至 grep,但我想不出找到客户端进程的方法。

MvG*_*MvG 28

此答案仅适用于 Linux。

更新为Linux 3.3:作为Zulakis在写单独的答案(+1说),你可以使用SSiproute2的得到一对inode编号的每个socket连接识别本端和同行。这似乎基于与sock_diag(7)相同的机制,具有UNIX_DIAG_PEER标识对等点的属性。一个答案通过Totor了在Unix和Linux堆栈交换链接到相关的提交内核iproute2的功能,还介绍了需要UNIX_DIAG的内核配置设置。

Linux pre 3.3 的原始答案如下。

根据Unix & Linux Stack Exchange的回答,我使用内核数据结构成功识别了 unix 域套接字的另一端,使用gdb和访问/proc/kcore。您需要启用CONFIG_DEBUG_INFOCONFIG_PROC_KCORE内核选项。

您可以使用lsof获取套接字的内核地址,它采用指针的形式,例如0xffff8803e256d9c0. 该数字实际上是相关内核内存结构或类型的地址struct unix_sock。该结构有一个名为的字段peer,它指向套接字的另一端。所以命令

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

将打印连接另一端的地址。您可以 grep 该lsof -U编号的输出以识别另一端的进程和文件描述符编号。

一些发行版似乎将内核调试符号作为单独的包提供,这将取代vmlinux上述命令中的文件。

  • @depesz,你只需要知道 `unix_sock` 结构中 `peer` 成员的偏移量。在我的 x86_64 系统上,该偏移量为 656 字节,因此我可以使用 `p ((void**)0xffff8803e256d9c0)[0x52]` 获得另一端。显然,您仍然需要`CONFIG_PROC_KCORE`。 (3认同)

Jac*_*cia 26

最近我偶然发现了一个类似的问题。我震惊地发现在某些情况下这可能是不可能的。我从 lsof (Vic Abell) 的创建者那里挖到了一条评论,他指出这在很大程度上取决于 unix socket 实现。有时所谓的套接字“端点”信息可用,有时则不可用。不幸的是,正如他指出的那样,这在 Linux 中是不可能的。

例如,在 Linux 上,lsof 必须使用 /proc/net/unix,所有 UNIX 域套接字都有一个绑定路径,但没有端点信息。通常没有绑定路径。这通常会导致无法确定另一个端点,但这是 Linux /proc 文件系统实现的结果。

如果您查看 /proc/net/unix,您可以亲眼看到(至少在我的系统上)他是绝对正确的。我仍然感到震惊,因为我发现这样的功能在跟踪服务器问题时必不可少。


Zul*_*kis 16

其实,ssfrom iproute2(代替netstat、ifconfig等)可以显示这个信息。

这是一个示例,显示了ssh进程已连接到的 ssh-agent unix 域套接字:

$ 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))
Run Code Online (Sandbox Code Playgroud)


小智 10

Unix 套接字通常成对分配编号,并且通常是连续的。所以你的配对可能是 1013410+/-1。看看这两者中的哪一个存在并猜测罪魁祸首。


lem*_*eze 8

我写了一个工具,它使用 MvG 的gdb 方法来可靠地获取套接字对等信息,不需要内核调试符号。

要将进程连接到给定的套接字,请将 inode 编号传递给它:

# socket_peer 1013410
3703 thunderbird 
Run Code Online (Sandbox Code Playgroud)

要一次找出所有进程使用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       
...
Run Code Online (Sandbox Code Playgroud)

netstat_unix --dump如果您需要易于解析的输出,请尝试。
有关详细信息,请参阅https://github.com/lemonsqueeze/unix_sockets_peers

有关信息,inode +1/-1 hack不可靠。它大部分时间都可以工作,但如果运气不好,它会失败或(更糟糕的是)返回错误的套接字。