当 ss 给不出进程归属
连接缺少进程归属时(老内核、权限不足、容器命名空间),可以用 socket inode 反查:先取 /proc/net/tcp 的 inode 列,再遍历 /proc/*/fd,找指向 socket:[inode] 的符号链接,命中的进程就是持有者。
为什么还要会这一手
这条路径不依赖任何工具适配:即使 ss、lsof 被替换或不可用,直接读内核暴露的 /proc 接口也能给出归属,属于应急时最基础的验证手段。
基本信息
| 入口 | /proc/net/tcp 及其 tcp6、udp 对应文件的 inode 列 |
|---|---|
| 反查方式 | 遍历 /proc/*/fd 匹配 socket:[inode] |
| 适用场景 | ss -p 显示不出 PID、lsof 未安装或结果不可信 |
| 替代手段 | lsof -i 直接给出 PID,但需安装且可能被替换 |
| 容器注意 | 宿主机看到的是宿主侧 PID,需进对应 netns |
| 权限要求 | 遍历全部进程 fd 需 root |
典型使用场景
- 确认某个监听端口究竟属于哪个进程
- 定位可疑外连对应的进程
- ss 与 lsof 输出异常时做交叉验证
- 容器内外的进程归属对齐
- 工具不可用时用最基础手段给出结论
按 inode 反查进程
按 inode 反查进程
ss -anp 'sport = :8080' | awk 'NR>1{print $NF; exit}' # 取该连接的 socket inode
INODE=12345678
for p in /proc/[0-9]*; do ls -l $p/fd 2>/dev/null | grep -q "socket:\[$INODE\]" && echo "$p ${p##*/}"; done
ls -l /proc/1234/fd 2>/dev/null | grep 'socket:' | head
readlink /proc/1234/exe /proc/1234/cwd逐项读法
| 来源 | 字段 | 说明 |
|---|---|---|
| /proc/net/tcp | inode 列(通常为末列) | 与 ss 输出一致,是反查的钥匙 |
| /proc/PID/fd | socket:[inode] 链接 | 命中即说明该进程持有该连接 |
| /proc/PID/cmdline | 进程命令行 | 用于确认进程身份与启动参数 |
| /proc/PID/cwd 与 exe | 运行目录与程序 | 指向 /tmp 等异常路径时提升可疑级别 |
ss 输出里 inode 的位置跟随选项变化,一般在最后一列:不要按固定列号硬编码,先加 -e 或直接核对表头位置。
遍历 /proc 需要 root:非 root 只能看到自己的进程,结论中必须注明权限限制,避免把「没查到」当成「不存在」。
容器场景的 netns 对齐
容器场景的 netns 对齐
docker inspect --format '{{.State.Pid}}' suspicious_container # 取容器主进程 PID
nsenter -t 12345 -n ss -antp | head -n 20 # 进入容器 netns 再看
nsenter -t 12345 -n cat /proc/net/tcp | head -n 10反查失败时的自查
- 进程已退出:fd 链接随之消失,只能回到历史快照与日志
- 连接由内核模块或内核自身持有,不属于任何用户进程
- 使用了独立网络命名空间,未进入对应 netns
- 目标进程处于不可中断状态,读取 /proc 时出现阻塞
反查后要一并核对的
- 进程的可执行文件路径与哈希
- 进程的命令行参数与启动用户
- 进程的父子关系与启动时间
- 该进程的监听端口在防火墙中的暴露情况