一、引言

原 Shell 命令通过 netstat -antp | grep "'+str(pid)+'/java" | grep LISTEN 获取 Java 实例的端口号,但某些机器或容器使用精简版 Linux,没有安装包含 netstat 的 net-tools,因此需要通过 Linux 的基本能力实现 netstat 的功能。

二、实现原理

netstat方法实现原理:

  1. 通过遍历/proc/<pid>/fd下文件夹去获取socket和inode的对应关系。

    • 假设已知程序的pid为8936。

    netstat结果

    • 首先对应的文件夹下查找所有包含socket的数据,socket后面那串数字就是inode节点索引。
    • 索引节点除了tcp,还可能有udp和unix本地连接,所以目录下可能会出现多个套接字。

    套接字

  2. 通过第一步获取的inode去/proc/net/tcp和/proc/net/tcp6匹配相应条目

    • 以下分别是tcp和tcp6的内容,两者的local_address和rem_address都是ip:port的结构。不同点在于tcp的ip长度为8位,tcp6的ip长度则为32位
    • 对比第4列的st(状态)和第10列的inode(索引节点)来筛选需要的数据,最终需要的是第10列的local_address(本机地址)部分的port(端口)

    /proc/net/tcp

    • 把获得的端口16转10进制获得最终结果。
  3. 名词解释

    • /proc/<pid>/fd:fd应该是file description的意思,此目录下存放该进程打开的所有fd。
    • inode索引节点包含文件的元信息,包括文件大小、读写权限等。inode是唯一的。
    • socket套接字是网络通信的概念,是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。

三、代码实现

#/bin/sh

if [ ! -n "$1" ];then
    echo "please enter pid"
    exit 0;
fi

inodes=`ls -al /proc/$1/fd | grep 'socket:' | sed 's/.*socket:\[\([0-9]*\).*/\1/g'`;
for inode in $inodes
do
    port=`cat /proc/net/tcp /proc/net/tcp6 | awk '{if($4 == "0A" && $10 == "'$inode'") print $2}' | cut -d: -f2`;
    if [ -n "$port" ];then
        echo $((16#${port}));
    fi;
done

四、参考文献

最后修改:2026 年 09 月 14 日
如果觉得我的文章对你有用,请随意赞赏