
字节笔记本
2026年10月7日 · 约 9 分钟读完
Linux 查端口占用:ss、lsof 与 netstat
端口被占的时候,先别去翻防火墙。Linux 上先回答一个更小的问题:谁在听这个端口。常用的有三条命令,netstat、lsof 和 ss。它们看的是同一张内核表,差别在于是不是还装在系统里、输出好不好读、以及要不要 root 才能看到进程名。

三条命令,同一组参数字母
查看所有 TCP 和 UDP 端口,三条写法几乎平行:
netstat -tunlp
lsof -i
ss -tunlp只看某一个端口时,对话里给的是再套一层过滤。80 端口的例子是:
netstat -tunlp | grep 80
lsof -i:80
ss -tunlp | grep 80字母的意思要先记住,不然每次都在抄整串:
t是 TCPu是 UDPn是直接显示端口号,不把 443 翻译成 httpsl是只看监听中的套接字,已经建立的连接先拿掉p是带上进程信息
lsof -i 不带这些字母,它列出所有网络文件。收成某一个端口时,语法是 lsof -i:80,冒号后面直接写端口,不要再 | grep。
ss 还可以拆开用。不带参数的 ss 是所有连接;ss -l 只看监听;ss -t 只看 TCP;ss -u 只看 UDP。日常查“谁占着端口”最常用的是 ss -tlnp,只要监听中的 TCP,并且带进程。UDP 监听换成 ss -ulnp。
优先用 ss,但进程名常常要 root
ss 来自 iproute2,是这三条里更该先敲的一条。netstat 属于 net-tools,很多新发行版默认已经不装,敲下去是 command not found,不是端口没人听。lsof 很适合确认某个端口对应的命令名,但完整的进程信息同样经常要 root。普通用户能看到自己的进程,别人的服务只会显示成一横,这时不要误判成“没有进程”。
grep 80 还有一个具体的误伤:它是子串匹配。8080、8000、44380 都会被捞进来。lsof -i:80 没有这个问题,因为端口是参数,不是文本。ss 想精确到一个端口,也不要靠 grep,直接写过滤表达式:
ss -tlnp sport = :80sport 是本地端口。这条只命中监听在 80 上的套接字,不会把 8080 算进去。
读输出时先看状态。监听中的一行状态是 LISTEN,已经连上的是 ESTAB。查“端口被占用、服务起不来”,看的是 LISTEN。查“这个端口现在有没有人在传数据”,才需要把 -l 拿掉,把已建立连接也打出来。
端口后面是路由,不是另一套魔法
端口没人听,或者听在了错误的地址上,下一步才是路由。笔记里并列了三条查看命令:route -n 打路由表,ip route show 是新的写法,netstat -r 打的是内核路由表。新系统上优先 ip route,route 和 netstat 往往跟 net-tools 一起缺失。
添加静态路由时,笔记里写的是网段经网关转发,旧命令和新命令各一条。把具体地址换成你自己的网段和网关即可,不要把示例里的私网地址抄进生产配置:
ip route add <网段>/<前缀> via <网关>临时加上的路由重启就没了。笔记里把永久配置指到了 /etc/sysconfig/network-scripts/ 这一类路径,那是 RHEL 系的习惯。Debian 和 Ubuntu 常见的是 netplan 或 /etc/network/interfaces,路径对不上时先确认发行版,不要在不存在的目录里找文件。
同一张配置图还列了日常会碰到的几个文件:/etc/resolv.conf 是 DNS,/etc/hosts 是本机名字解析,/etc/hostname 是主机名,/etc/services 是服务名和端口的对照。/etc/sysctl.conf 则是内核参数,MTU、转发开关这类改动经常落在这里,而不是落在 ss 的输出里。
先确认有没有人在听
端口问题的顺序可以固定下来。先 ss -tlnp 看有没有 LISTEN,进程名看不到就加 sudo 再看一次。要锁定某一个端口,用 sport = :端口 或 lsof -i:端口,不要用 grep 去碰端口号子串。确认没有进程之后,再查路由和 DNS 文件。防火墙、NAT、MTU 都在这条链的后面。一上来改规则,往往会把一个单纯的“进程还在”修成更难查的网络问题。
端口通了之后,再测连通和 MTU
人在听,不代表数据包走得过去。笔记里把连通性测试收成几条很短的命令。ping 目标看基本连通,ping -c 4 只发四次就停,避免一直挂着。ping -i 0.2 把间隔改成 0.2 秒,这个间隔通常要 root。traceroute 看中间经过哪些跳,加上 -n 不解析主机名,排障时更快,也少一次 DNS 干扰。DNS 本身用 dig 或 nslookup 查名字,和 ping 通不通是两件事:名字解析失败时,ping IP 仍然可能通。
抓包是最后一步,不是第一步。tcpdump -i eth0 看某一块网卡,tcpdump port 80 只看 80 端口。网卡名在不同机器上不是 eth0,先用 ip addr show 看实际名字,再替换 -i 后面的参数。ifconfig 仍出现在旧笔记里,用来开关网卡或改地址,新系统上同样优先 ip。
MTU 在那张图里写的是常见的 1500 字节。以太网帧另有两个数:头部 14 字节加上末尾 4 字节的 FCS,最大帧长 1518 字节,最小帧长 64 字节。IP 包超过路径 MTU 就会分片。笔记里用一条带禁止分片的 ping 来探测:ping -s 1472 -M do,因为 1472 再加上 28 字节的 IP 和 ICMP 头,正好是 1500。这一跳返回需要分片,就说明路径上有人比 1500 更小。改本机网卡的 MTU,旧命令是 ifconfig eth0 mtu 1500,改完仍要用同一条 ping 复核,而不是只看配置文件里写了多少。
NAT 是另一层:很多机器没有公网地址,出去的包会在网关被改写源地址。ss 能看到本机谁在听,看不到办公室网关怎么做地址转换。本机端口没人听,就先别改 NAT。本机有人听但外网访问不到,再去看网关和防火墙。顺序反了,两边的配置会一起变成未知数。
数据从应用到网线,笔记里还按层写过单位:应用数据装进段,再装进 IP 包,再装进以太网帧。查端口时你看的是传输层的端口号。MTU 和分片发生在往下的层。端口显示正常、大包却丢,就不要再反复重启监听进程,把 1472 那条 ping 跑一下。

把 ss 的一行读完
ss -tlnp 的一行里,先看本地地址,再看进程。本地地址如果只绑在回环接口上,本机进程能连,同一局域网里的别的机器不能连。这和“端口没有人听”是两种结果:进程在,防火墙也没关,只是它没有绑到对外的地址。笔记里的 ss -tunlp 会把 UDP 一起打出来。DNS 和部分发现服务走 UDP,用只含 -t 的命令会误以为那些端口是空的。
进程列要 root 才完整,这个限制对 lsof -i 同样存在。普通用户看到进程列为空,先提权再查一次,不要立刻去改 /etc/sysctl.conf。/etc/services 能把端口号翻译成服务名,ss 加了 -n 就是故意不翻译,排障时数字比名字可靠,因为同一台机器上的实际服务不一定按 /etc/services 里的传统名字在跑。
防火墙文件在那张配置图里单列了一组:firewalld 的目录、iptables 的规则文件,以及 IPv6 的规则文件。它们决定包能不能到达已经在听的进程。ss 显示 LISTEN 而外面连不上,才打开这些文件。本机 ping 自己的地址是通的,只能说明协议栈还在,不能说明防火墙放行了那个端口。tcpdump port 80 如果能看到外面进来的 SYN,而应用没有反应,问题在监听进程。一个包都看不到,问题在到达本机之前,包括路由和 NAT。
1472 那条 ping 专门测路径 MTU,不要把它当成连通性测试的替代。-c 4 的普通 ping 先确认通不通,通了再加大包并禁止分片。禁止分片之后如果失败,把载荷减小再试,找到能通过的最大值,再加上 28 字节,就是这一路上的 MTU。本机网卡仍写着 1500,并不推翻这个结果,因为更小的限制可能在中间某一跳。



