Linux端口查询实战:进程名与端口号互查全攻略
2026/9/18 21:35:55 网站建设 项目流程

1. 先搞清楚进程和端口是怎么对应上的

很多刚接触Linux的朋友都会遇到同一个困惑:部署了一个服务,明明进程起来了,但怎么都访问不到,或者是端口冲突了,却不知道该杀谁。说来说去,就是“进程”和“端口”之间这条线没连上。今天就把这个事儿彻底捋明白:怎么根据进程名查出它占用的端口号,又怎么根据端口号反查是哪个进程在用。

Linux下一个网络服务要对外提供服务,实际上干的事情就是:进程启动后创建一个socket,把这个socket绑定到某个IP和端口上,然后进入监听状态。这个过程中,内核会维护一张对应关系表,记录着端口号、协议类型、进程PID、进程名这些信息。我们查端口和进程的关系,本质上就是查这张表。

打个比方,一台服务器就像一栋写字楼,端口号是楼里的门牌号,进程是入驻的公司。你要找人,要么拿着公司名去查它在几零几,要么看到一个门牌号反查是什么公司在里面办公。两种方向都要会,排查问题时才能省时间。

这里要强调一个基础认知:一个进程可以监听多个端口,一个端口同一时间只能被一个进程监听(复用除外,这个后面讲)。所以当你看到“端口被占用”的报错时,不用慌,系统里一定有一个确切的PID在占着它,找到它就行。

核心工具就三个家族:sslsofnetstat,外加一个快速定位nmapfuser。虽然netstat是老牌命令,但很多新系统默认不装了,我更推荐ss,它是iproute2包自带的,几乎每个发行版都有,而且查询速度比netstat快很多,在端口多的服务器上差别尤其明显。

2. 根据进程名查端口号:三种常用姿势

2.1 第一步先定位进程的PID

给定一个进程名要查端口,最直接的思路是先用pgreppidof拿到PID,再通过PID去反查它打开的端口。

# 根据进程名找到PID pgrep -a nginx # 输出示例 12345 nginx: master process /usr/sbin/nginx 12346 nginx: worker process 12347 nginx: worker process # 或者用 pidof,只输出PID数字 pidof nginx # 输出示例 12347 12346 12345

这里建议用pgrep -a,因为它同时显示PID和完整的命令行,能帮你确认是否是你要找的那个进程。比如服务器上可能同时存在好几个Java进程,光看进程名可能分不清,但pgrep -a java能看到每个PID对应的启动参数,是哪个服务一目了然。

还有一种情况是进程名特别长,被内核截断了,这时pgrep -f可以匹配完整的命令行参数:

pgrep -f "java.*order-service"

它会把所有命令行里包含order-service关键字的进程都列出来,非常适合排查多实例部署的场景。

2.2 拿到PID后,用ss或lsof查开放端口

拿到PID之后,下一步就简单了。sslsof都支持按PID过滤。

ss按进程PID查:

ss -tulnp | grep "pid=12345"

这里我要解释一下-tulnp这组参数的含义,很多人只知道抄参数,不知道每个字母是什么意思。-t表示查看TCP协议,-u表示查看UDP协议,-l表示只显示监听状态的连接,-n表示不对IP和端口做反向解析(不加这个会很慢,因为每次都要反查DNS),-p表示显示进程信息。把这五个参数拼在一起,就是“查看所有监听中的TCP和UDP端口,并且显示对应的进程PID和进程名”,这是日常使用频率最高的一条命令。

lsof按进程PID查:

lsof -p 12345 | grep LISTEN # 或者只看TCP/UDP端口相关 lsof -Pan -p 12345 -i

第一条的-Pan也有讲头。-P禁用端口名解析(不把80显示成http),-a表示后面的条件需要同时满足,-n禁用主机名解析。如果你不加-P-nlsof默认会尝试把端口号解析成服务名、把IP解析成主机名,虽然也能看,但输出会多一层转换,还容易因为DNS解析卡顿。实际排查时建议都加上,输出更干净、速度更快。

不过说实话,在实际工作里我很少这样分两步走。ss本身就能同时显示进程名和端口,如果你只是想快速看一眼,根本不用先拿PID:

ss -tulnp | grep nginx

2.3 一条命令直接出结果:ss和lsof的进阶用法

如果环境中没有ss,或者你想用更专业的排查姿势,可以直接一条命令完成“进程名→端口”的查询。

# 通过进程名直接找端口 ss -tulnp | grep -E "nginx|php-fpm" # 如果只想看某个进程名的监听端口,过滤列更精准 ss -tulnp | awk '/nginx|php-fpm/ && /LISTEN/ {print $4, $0}'

我这里举个完整的实操例子。有一次我在给客户部署一套Web应用,Nginx和PHP-FPM都配好了,但访问页面一直502。我当时的第一个动作就是确认两个服务真的在监听各自的端口:

ss -tulnp | grep -E "nginx|php-fpm"

输出内容大概是这样的:

LISTEN 0 128 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=12345,fd=6)) LISTEN 0 128 0.0.0.0:9000 0.0.0.0:* users:(("php-fpm",pid=12518,fd=8))

看到两个端口都在监听,我才确定问题出在Nginx配置里的fastcgi_pass写成了127.0.0.1:9000,而PHP-FPM监听的是0.0.0.0:9000,本地IPv4回环连接实际上是通的,但IPv6回环::1不通,导致部分请求失败。这个例子只是想说明:查端口只是第一步,查完之后还得结合监听地址来判断配置是否匹配。0.0.0.0127.0.0.1的区别,很多时候就是问题根源。

再说lsof的一条命令版本:

# 通过进程名关键字直接查端口 lsof -Pan -i -a -c nginx # -c 后面跟进程名的开头字母,比如 mysqld 可以写 -c mysql lsof -i -a -c java

-c参数匹配的是进程名的前缀,不是精确匹配,所以某些进程名很相似的场景下可能会多匹配出一些结果,需要自己再肉眼过滤一下。用的时候心里有数就行。

另外不得不提一个情况:如果你装了nmap,它也可以用来查本机的端口和进程关系,但它更适合查远端主机,本机排查用不上,这里就不展开了。

3. 根据端口号反查进程名:反向排查三板斧

3.1 ss -tulnp 一步到位

网页打不开、端口被占用、服务起不来……这些场景都是从端口反查进程。这时候第一板斧就是ss

# 查看所有监听端口及其对应进程 ss -tulnp # 精确查看某个端口 ss -tulnp | grep ':8080' # 不区分TCP/UDP,直接看占用该端口的进程 ss -lunp | grep ':53'

举一个真实发生的例子。我之前在测试环境启动Spring Boot应用,端口配的是8080,结果启动报错:

Port 8080 was already in use.

我第一条命令就是:

ss -tulnp | grep ':8080'

输出:

LISTEN 0 128 0.0.0.0:8080 0.0.0.0:* users:(("java",pid=26514,fd=32))

这一下就锁定了是PID 26514的Java进程占着8080端口。再通过ps -fp 26514查看这个进程的完整命令行,发现是另一个环境的测试服务忘记关掉了,直接kill掉就解决了。

这里有个小细节值得提醒:grep ':8080'两端我都加上了冒号,grep '8080'可能匹配到1808080801等包含8080的端口,用冒号做分隔符能规避掉不少误匹配。端口号后面还有IP地址,直接grep 8080确实容易误伤。

3.2 lsof -i:端口号,定位更精准

如果想看单个端口的详细信息,lsof更直观。它的输出会列出进程PID、进程名、文件描述符FD、协议类型等信息。

# 精确查看某个端口 lsof -i:8080 # 同时看TCP和UDP lsof -i:53 # 只看TCP的3306 lsof -iTCP:3306

lsof -i:8080的输出大概是这样的:

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME java 13784 root 32u IPv6 123456 0t0 TCP *:8080 (LISTEN)

这一行信息量非常大。COMMAND是进程名,PID是进程号,USER是以什么身份在跑,TYPE显示的是IPv6,这提醒我这个进程是在IPv6协议栈上监听的。FD是文件描述符编号,NAME*:8080可以看到它监听了所有网卡的8080端口。

实际排查中经常遇到一种情况:用ss查不到任何进程,但lsof能查到。或者说反过来。这不是工具本身有问题,而是两个命令读取的信息源和处理方式不同。遇到一个查不到的情况,就用另一个交叉验证,基本不会漏。

lsof还支持查看某个端口范围的占用情况:

# 查看从8000到9000范围内的所有监听端口 lsof -i:8000-9000

这个功能在做端口规划的时候特别有用。比如你有一个新服务需要选一个没被占用的端口,直接lsof -i:8000-9000把这段都列出来,一眼就能看到哪些端口是空闲的。

3.3 占用端口杀不掉?fuser来帮忙

fuser这个命令在端口排查里出场率不高,但在“端口被占用且确定要杀掉”的场景下非常好用。它可以直接根据端口号反查出占用的进程PID,甚至可以直接帮你kill掉。

# 查看占用8080的进程 fuser 8080/tcp # 直接杀掉占用8080的进程(慎用) fuser -k 8080/tcp # 查看详细进程信息 fuser -v 8080/tcp

fuser -v的输出会显示进程的完整命令行,比单纯一个PID更有参考价值。但我要提醒一句,fuser -k杀进程之前一定要通过-v确认目标进程的身份,尤其是线上环境,直接kill可能干掉别人的服务。我有一次就是图省事,在客户机器上执行了fuser -k 9000/tcp,结果把对方一个还没上线的监控程序给杀了,虽然是小事故,但也很尴尬。正确的做法是先用fuser -v确认,再决定要不要动手。

如果不想用fuser,用组合命令也能实现同样的效果:

# 杀端口前先确认 ss -tulnp | grep ':9000' # 确认无误后再kill PID kill -9 <PID>

这套流程虽然多几步,但每步都明明白白的,适合在重要机器上操作。

4. 典型问题排查与避坑记录

4.1 明明有进程在跑,查不到监听端口?

这应该是新手最容易困惑的问题。我在论坛上看到过一个典型的帖子:Nginx进程状态明明是running,但ss -tulnp | grep nginx就是看不到任何输出。

这种场景多半是进程崩溃后退出了但残留了PID文件,或者压根是cgroup/容器层面的状态不同步。排查步骤应该是这样:

  1. 先用ps -ef | grep nginx确认进程是否真的存在,不要只看systemd状态。
  2. 如果进程存在,再用ss -tulnp | grep <PID>看看它有没有打开监听端口。
  3. 如果什么都没有,基本可以断定配置里没有开启监听,或者监听失败了(比如配置文件语法错误导致实际没有监听),去检查该服务的配置文件、日志和启动命令,重点看listen指令。

还有一种非常容易踩的坑:改了配置文件后忘记重启服务。我见过有人改完Nginx配置文件,reload了一下但没生效,导致新端口没监听上,但还是摸不着头脑。排查端口问题前,先确认你已经用当前配置文件重启了服务,否则一切排查都是徒劳。

4.2 ss和netstat输出对不上?内核态与用户态的差异

在我早期的运维工作中,有一次我同时用了netstatss查同一个端口,两边显示的状态居然不一样,一个显示LISTEN,一个什么都没显示。查了很长时间才弄清楚:ss直接读内核的socket hash表,信息是实时的;netstat在部分系统上会读取/proc/net/tcp等文件,两者在极端情况下会有短时间的差异。

所以我的建议是:新环境优先用ss,它快且准,还在持续维护。netstat虽然经典,但在新版系统上不一定装,且输出格式旧。很多老教程还在教netstat -ano,如果你用的系统没装,直接apt install net-toolsyum install net-tools装一下也行,但长期来看适应ss更划算。

另外ss输出里有一列Recv-QSend-Q,能反映一个连接上是否有堆积数据。排查网络问题时,这两个值很有参考意义。比如Recv-Q长期不为零,说明应用处理不过来了。

4.3 端口被占用但PID不对,或者PID消失

有时你查到一个端口被占用,拿到了PID,但ps -fp PID提示这个进程不存在。这种情况常见于短生命周期进程或已退出的子进程,端口可能被内核挂在某个连接上,处于TIME_WAIT状态。

比如一个服务频繁重启,旧的连接还处于TIME_WAIT,虽然进程已经退出了,但内核里端口对应的记录还没完全回收。这时ss -tan能看到一堆TIME_WAIT状态的连接。如果新进程还是起不来,多半不是端口没释放,而是有其他问题。

遇到“端口占用但PID不存在”的情况,可以用这个命令看本地端口的所有连接状态:

ss -tan | grep ':8080'

如果是TIME_WAIT,通常等待内核自动回收就行(一般是60秒左右),不用急着处理。如果你是在反复重启服务做测试,可以临时调整内核参数,但生产环境不建议动这些参数,保持默认就行。

4.4 容器场景下的端口查询

现在很多服务都跑在Docker或Kubernetes里,端口查询和物理机上略有不同。容器网络模式下,容器的端口映射是在宿主机上通过docker-proxyiptables规则实现的。

如果你的服务跑在容器里,在宿主机上执行:

ss -tulnp | grep ':8080'

看到的进程往往是docker-proxy或者containerd,而不是你容器里的Java或Nginx进程。这是正常的,不必惊慌。你真正应该进容器内部去看:

docker exec -it <容器名> ss -tulnp

或者用docker ps查看端口映射关系:

docker ps --format "table {{.Names}}\t{{.Ports}}"

如果是在Kubernetes环境里,网络排查更绕,Pod里的端口和Node端口之间还隔着一层kube-proxy。我的建议是:先确认你正在排查的“进程”和“端口”处于同一个网络命名空间。否则你看到的“占用”可能只是代理层的表现,不是事情的真相。

4.5 用一个脚本解决“批量查端口”需求

最后分享一个我日常用来做端口审计的小脚本。服务器上跑着几十个服务,逐个ss太慢了,脚本一次把所有监听端口和进程对应关系列出来,还能排除掉系统预留端口:

#!/bin/bash # 按服务名查看端口占用概览,排除系统常见端口 ss -tulnp | tail -n +2 | awk '{print $1, $4, $6}' | sed 's/.*users:((//;s/)).*//' | sort | uniq -c | sort -rn | head -30

这段脚本做的事情是:去掉表头,只留下协议、本地地址和进程信息,然后提取进程信息里的关键部分,统计每个进程打开了多少个监听端口。输出结果能一眼看出哪个进程开的端口最多,适合做服务梳理和端口台账盘点。当然,脚本的统计逻辑比较粗糙,生产环境用的话建议再根据自己需求做定制。

排查Linux端口问题时,最忌讳的是慌。端口和进程的对应关系就摆在那里,不是查不到,只是没找对工具。ss不行就换lsof,TCP查不到就试试UDP,宿主机查不到就进容器,总有一条路径能走到答案。我个人实操中的体会是,把ss -tulnp的每个参数含义记熟,比背一百条命令都管用,因为这个命令本身已经覆盖了九成以上的端口排查需求。剩下的功夫,都花在理解你的服务到底是怎么监听端口的上面。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询