我需要知道具有给定 PID 的进程是否在不使用外部命令的情况下打开了端口。然后我必须使用/proc
文件系统。例如,我可以读取该/proc/$PID/net/tcp
文件并获取有关进程打开的 TCP 端口的信息。但是,在多线程进程上,该/proc/$PID/task/$TID
目录还将包含一个net/tcp
文件。我的问题是:
我是否需要检查所有线程net/tcp
文件,或者将线程打开的端口写入进程net/tcp
文件中。
答案1
例如,我可以读取 /proc/$PID/net/tcp 文件并获取有关进程打开的 TCP 端口的信息。
该文件不是由过程。它是当前网络命名空间中所有打开的tcp端口的列表,对于在同一网络命名空间中运行的进程来说是完全相同的的内容/proc/net/tcp
。
要查找进程打开的端口,您需要从 获取套接字描述符列表/proc/<pid>/fd
,然后将这些描述符与inode
的字段进行匹配/proc/net/tcp
。
答案2
请
cat /proc/$PID/net/tcp
你会得到这样的输出
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 00000000:01BB 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 2891985097 1 0000000000000000 100 0 0 10 0
local_address
输出的第二列 ( ) 以十六进制显示端口。使用编程计算器将十六进制代码转换为十进制。
例如,端口 :01BB(十六进制)等于 443(十进制),这是 HTTPS 默认端口。
答案3
作为旁注,/proc/net/tcp
已被 取代NETLINK_SOCK_DIAG
,它本质上以二进制形式为您提供相同的数据,并且根据实现者的说法,比从/proc/...
文件夹中读取更快、更安全。
有库(libmnl
是基础库),并且该功能在许多语言中都可用(C/C++ 可以直接访问这些库,Go 和 Python 有扩展,我认为 perl 也有,当然还有许多其他语言)。
由于您没有透露您使用的是哪种语言,因此目前很难说更多。我在 Stackoverflow 上有一个 C 示例实现:https://stackoverflow.com/questions/68425240/can-the-netlink-sock-diag-interface-be-used-to-listen-for-listen-and-close
答案4
下面是示例脚本,它发现套接字描述符的 inode 并显示已打开此套接字的正在运行的进程的 PID。
port=9090;
hex_port=$(python -c 'print(hex('$port')[2:])');
inode=$(cat /proc/net/tcp | grep ":$hex_port" | awk '{print $10}');
for i in $(ps axo pid); do
ls -l /proc/$i/fd 2> /dev/null | grep -q ":\[$inode\]" && echo $i;
done