用于确定进程拥有的套接字的 Linux API
Posted
技术标签:
【中文标题】用于确定进程拥有的套接字的 Linux API【英文标题】:Linux API to determine sockets owned by a process 【发布时间】:2010-12-31 02:56:58 【问题描述】:是否有一个 Linux 库可以让我知道哪些 IP 套接字由哪些进程拥有?我想我正在寻找lsof -i
的程序等效项。最终,我想将通过libpcap
看到的数据包与进程相关联。
更新:有几个人建议使用/proc/<pid>/net/tcp
和udp
,但在我的系统上,每个进程都显示相同的数据,所以没有帮助。 p>
【问题讨论】:
哇哦。我现在正在写一个程序来做这个,真是巧合 如果您有兴趣比较笔记,我现在有代码。我在 /proc 数据中看到了一些罕见的怪癖,但总体而言该方法有效。 【参考方案1】:我认为您首先必须查看 /proc/*/fd 中打开的 fd,例如
4 -> socket:[11147]
然后在 /proc/net/tcp(或 /proc/net/udp)中查找引用的套接字(通过 inode),例如
12: B382595D:8B40 D5C43B45:0050 01 00000000:00000000 00:00000000 00000000 1000 0 11065 1 ffff88008bd35480 69 4 12 4 -1
【讨论】:
这是缺少的链接。谢谢! (由于某种原因不会让我投票。) 你在我写作的时候回答了这个问题,我没有注意到...干得好:) +1,因为 OP 显然不能。 如果两个示例中的 inode 相互匹配,这个答案可能会更好。 看/proc/XXX/net/tcp,里面只有pid为XXX的进程打开的socket。 fossilet, /proc/要确定进程拥有的套接字,您可以使用netstat
。这是一个带有netstat
的输出(缩短)的示例,其中包含可以满足您需求的选项。
$ sudo netstat -apeen
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name
tcp 0 0 127.0.0.1:8118 0.0.0.0:* LISTEN 138 744850 13248/privoxy
tcp 0 0 127.0.0.1:5432 0.0.0.0:* LISTEN 117 9612 2019/postgres
udp 0 0 127.0.0.1:51960 127.0.0.1:51960 ESTABLISHED 117 7957 2019/postgres
udp 0 0 0.0.0.0:68 0.0.0.0:* 0 7740 1989/dhclient
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags Type State I-Node PID/Program name Path
unix 2 [ ACC ] STREAM LISTENING 7937 2019/postgres /var/run/postgresql/.s.PGSQL.5432
unix 2 [ ACC ] STREAM LISTENING 958058 8080/emacs /tmp/emacs1000/server
unix 2 [ ACC ] STREAM LISTENING 6969 1625/Xorg /tmp/.X11-unix/X0
unix 2 [ ] DGRAM 9325 1989/dhclient
unix 3 [ ] STREAM CONNECTED 7720 1625/Xorg @/tmp/.X11-unix/X0
确保您以 root 身份运行 netstat,否则您将收到此消息:
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
netstat manpage 中-apeen
选项的解释:
-a, --all
Show both listening and non-listening sockets. With the
--interfaces option, show interfaces that are not up
-p, --program
Show the PID and name of the program to which each socket
belongs.
-e, --extend
Display additional information. Use this option twice for
maximum detail.
--numeric , -n
Show numerical addresses instead of trying to determine symbolic host, port or user names.
--numeric-hosts
shows numerical host addresses but does not affect the resolution of port or user names.
--numeric-ports
shows numerical port numbers but does not affect the resolution of host or user names.
--numeric-users
shows numerical user IDs but does not affect the resolution of host or port names.
【讨论】:
如果您向该进程的所有者发送 sudo(如果您无法获得 root),您可以获得 pid。对此解决方案 +1!谢谢!netstat
实际上会解析 /proc/net/tcp
等。参见,例如,here(/proc/net/tcp
的解析代码)。 lib/pathnames.h
中定义的 netstat 使用的路径。【参考方案3】:
/proc
文件系统提供每个进程的详细信息,包括网络信息。在/proc/net/tcp
中列出了打开的套接字信息。 IPv6 套接字在tcp6
文件中单独列出。套接字信息包括本地和远程端口、套接字inode号等信息,可以通过解析/proc/pid/fd/*
信息映射回进程。
如果您不熟悉/proc
文件系统,它基本上是一个虚拟文件系统,允许内核将各种有用的信息发布到用户空间。这些文件通常是易于解析的简单结构化文本文件。
例如,在我的 Ubuntu 系统上,我使用 netcat
进行测试,并运行 nc -l -p 8321
监听 8321 端口。查看 tcp
套接字信息:
$ cat /proc/net/tcp
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 00000000:2081 00000000:0000 0A 00000000:00000000 00:00000000 00000000 1000 0 26442 1 de0c8e40 300 0 0 2 -1
1: 0100007F:0277 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 7019 1 de0c84c0 300 0 0 2 -1
第一行显示它正在监听到点 8321 (0x2081) 的所有地址。 inode 编号是 26442,我们可以使用它在/proc/pid/fd/*
中查找匹配的 pid,它由一堆从文件句柄编号到设备的符号链接组成。因此,如果我们查找netcat
的pid,并检查其fd
映射:
$ ls -l /proc/7266/fd
total 0
lrwx------ 1 gavinb gavinb 64 2009-12-31 09:10 0 -> /dev/pts/1
lrwx------ 1 gavinb gavinb 64 2009-12-31 09:10 1 -> /dev/pts/1
lrwx------ 1 gavinb gavinb 64 2009-12-31 09:10 2 -> /dev/pts/1
lrwx------ 1 gavinb gavinb 64 2009-12-31 09:10 3 -> socket:[26442]
我们看到这个进程中的文件描述符 3 被映射到 inode 26442 的套接字,正如我们所期望的那样。
显然,要构建完整的套接字映射,您需要首先枚举所有/proc/**/fd/*
文件,查找套接字符号链接,然后将套接字inode 与/proc/net/tcp
中具有端点信息的表进行匹配。
这就是lsof
工具的工作方式(请参阅lsof/dialects/linux/dsocket.c
了解实现)。
【讨论】:
与我对 Kimvais 的问题相同:/proc/*/net/tcp 目录为不同的 pid 显示相同的数据。如何将每个映射回源 pid? 我已经更新了答案,以包含有关如何将套接字映射到 pid 的完整描述。我希望这现在更清楚了——它基本上涉及为套接字 inode 构建一个 pid 表,并在 tcp 套接字表中查找这些 inode。让我知道是否有任何需要澄清的地方。【参考方案4】:/proc/<pid>/net
等同于 /proc/net
与您在同一网络命名空间中的所有进程 - 换句话说,它是“全局”信息。
您可以执行 lsof
和 fuser
所做的事情,即遍历 /proc/<pid>/fd/*
和 /proc/net/*
寻找匹配的 inode。快速演示:
#!/bin/sh
pgrep "$@" | while read pid; do
for fd in /proc/$pid/fd/*; do
name=$(readlink $fd)
case $name in
socket:\[*\])
ino=$name#*:
for proto in tcp:10 tcp6:10 udp:10 udp6:10 unix:7; do
[[ ! -e /proc/net/$proto%:* ]] ||
awk "
\$$proto##*: == $ino:1:$#ino-2
print \"$proto%:*:\", \$0
exit 1
" /proc/net/$proto%:* || break
done
;;
esac
done
done
您可以将其扩展到其他协议(我在 /proc/net/
中也看到 ax25、ipx、packet、raw、raw6、udplite、udp6lite)或用您选择的语言重写。
【讨论】:
【参考方案5】:您可以从 proc 文件系统中读取它们。您可能想要查看的“文件”位于
/proc/<pid>/net
(即tcp、udp、unix)
这里有一些关于使用 proc 文件系统的examples
【讨论】:
也许我遗漏了一些东西,但是 /proc/*/net/tcp 为不同的 pid 显示了相同的数据。必须显示所有连接。如何将每个映射回源 pid?【参考方案6】:您可以尝试使用 strace 运行 lsof 并查看它从 /proc 中的哪些文件获取数据。
【讨论】:
【参考方案7】:我会去源头:
http://ubuntuforums.org/showthread.php?t=1346778
【讨论】:
以上是关于用于确定进程拥有的套接字的 Linux API的主要内容,如果未能解决你的问题,请参考以下文章