macOS 上 lsof 查端口查不到?不是端口没被占,是你没权限看见
最常出现的场景是:本地起一个 Node/Flask 开发服务器,习惯性绑定 5000 端口,启动报 address already in use;跑 lsof -i :5000 想看看是谁占着,输出却空空如也。这不是端口其实没被占,也不是 lsof 有 bug——是这个端口被一个你这个普通用户看不到的进程占着,lsof 没权限看,就直接把它当”不存在”处理,不会报权限错误提示你。
原因:lsof 只能看见你自己有权限看的进程
lsof 遵循标准 Unix 权限模型:不带 sudo 跑的时候,只能看到当前用户自己名下进程的文件描述符(网络连接本质上也是一种文件描述符)。占着端口的进程如果是以 root 或者别的系统账号身份跑的,普通用户身份的 lsof 天生看不到——不是权限报错,是这些条目直接不出现在输出里。
macOS 上最典型的撞坑场景就是端口 5000/7000:Monterey 之后系统设置里的”AirPlay 接收器”默认是开着的,开启之后会自动占用这两个端口,用来接收 iPhone 或者别的 Mac 投过来的 AirPlay 流。管这个功能的进程是 ControlCenter,运行身份不是当前登录用户,所以普通用户身份查不到它。
解决:加 sudo,还查不到就换参数
1 | sudo lsof -i :5000 |
如果这样还是看不全,换成更完整的参数组合:
1 | sudo lsof +c0 -nP -i4TCP:5000 |
这条跑完能看到 ControlCenter 正监听着 5000 端口。确认是它之后,解决办法很直接:系统设置里把 AirPlay 接收器关掉,端口就放出来了;不想关这个功能的话,本地开发服务器换个端口(比如 5001)比跟系统抢端口更省心。
加了 sudo 还是查不到:可能是 SIP 在拦着
sudo lsof 能解决绝大部分”看不见系统级服务”的情况,但 macOS 在标准 Unix 权限之上还叠了一层系统完整性保护(SIP),部分被 SIP 特别保护的系统路径和进程,即便是 root 权限也介入不了。真遇到 sudo lsof 依然查不到、又高度怀疑是系统层面的东西占着端口,与其继续跟 lsof 较劲,不如直接去系统设置里翻一遍”共享””AirDrop 与接力”这类开关——答案很多时候就在那儿。
记住这条判断准则就够了:lsof 查不到不等于端口没被占,遇到冲突先加 sudo 再看一遍。










