4. macOS 端口排查:lsof、netstat 与 Activity Monitor

说实话,macOS 上的端口排查,跟 Linux 有点像,但又有不少坑。我刚开始从 Linux 切到 macOS 做开发时,第一反应就是——netstat 怎么参数不一样了?后来才慢慢摸清门道。

这一节,我带你过一遍 macOS 上最实用的几个工具:lsof -i、netstat -an,还有图形化的 Activity Monitor。最后再聊聊那个让人头疼的 "port already in use" 怎么解决。

4.1 lsof -i:我的首选武器

我个人习惯,排查端口问题第一个想到的就是 lsof。它全称是 "list open files",在 Unix 世界里,一切皆文件,网络连接也不例外。

最常用的命令就这一条:

sudo lsof -i :端口号

比如,我想看看 8080 端口被谁占了:

sudo lsof -i :8080

输出大概长这样:

COMMAND   PID   USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
java    12345  zhangsan  123u  IPv6 0x123456789abcdef      0t0  TCP *:8080 (LISTEN)

关键信息一目了然:

  • COMMAND:哪个程序占的(这里是 java)
  • PID:进程 ID(12345)
  • USER:哪个用户跑的
  • NAME:具体监听地址和状态(LISTEN 表示正在监听)
小技巧:不加 sudo 的话,你只能看到自己用户的进程。很多系统服务或别人启动的进程,你看不到。所以,养成好习惯——先 sudo。

如果想看所有正在监听的端口,可以这样:

sudo lsof -i -P | grep LISTEN

这里的 -P 参数很关键——它让 lsof 不把端口号解析成服务名。你想想看,显示 "8080" 比显示 "http-alt" 直观多了吧?

4.2 netstat -an:老牌工具,参数有坑

macOS 自带的 netstat 跟 Linux 版不太一样。我第一次在 Mac 上敲 netstat -tlnp,结果报错——根本没这个参数。

macOS 上正确的用法是:

netstat -an | grep LISTEN

或者想看某个特定端口:

netstat -an | grep 8080

输出示例:

tcp4       0      0  *.8080                 *.*                    LISTEN
tcp6       0      0  *.8080                 *.*                    LISTEN

这里 tcp4 和 tcp6 分别代表 IPv4 和 IPv6 的监听。有时候你会发现同一个端口出现两次,别慌,这是正常的——一个应用同时监听了两种协议。

注意:macOS 的 netstat 没有 -p 参数来显示进程名。想看哪个进程占用了端口,还得靠 lsof。所以我的习惯是:快速扫一眼用 netstat,深挖用 lsof。

4.3 Activity Monitor:图形化排查

有些时候,你不想敲命令,或者你正在给一个不太熟悉命令行的同事远程指导——这时候 Activity Monitor(活动监视器)就派上用场了。

打开方式:

  • 在 Launchpad 里搜 "活动监视器"
  • 或者用 Spotlight(Cmd+Space)直接搜

怎么用它查端口?嗯,这里有个小技巧——它本身不直接显示端口号。但你可以这样:

  1. 打开 Activity Monitor
  2. 在搜索框里输入进程名(比如 java、python)
  3. 双击进程,点 "打开文件和端口"
  4. 在列表里找 TCP 类型的条目,端口号就在后面

这个方法比较笨,但胜在直观。我记得有一次帮一个前端同事排查问题,他死活记不住 lsof 命令,我就让他用 Activity Monitor 找到了占端口的 Node.js 进程。

4.4 解决 "port already in use"

这个错误,我相信每个人都遇到过。你启动服务,啪,报错:

Error: listen EADDRINUSE: address already in use :::8080

为什么会这样?说白了,就是你要用的端口已经被别的进程占用了。解决思路无非两条:

  • 杀掉占用的进程
  • 换一个端口

先查出来是谁占的:

sudo lsof -i :8080

拿到 PID 之后,直接杀掉:

sudo kill -9 12345

这里 -9 是强制杀死,有时候进程比较顽固,普通 kill 杀不掉。

避坑指南:我曾经在服务器上 kill 了一个进程,结果发现是数据库的端口。嗯,那场面……所以杀之前,一定看清楚 COMMAND 那一列是什么程序。不确定的话,先 ps aux | grep PID 确认一下。

如果你不想杀进程,那就换个端口启动。比如把 8080 改成 8081:

# 以 Node.js 为例
PORT=8081 npm start

或者改配置文件里的 server.port 之类的参数。

4.5 知识体系总览

下面这张图,帮你把 macOS 端口排查的整个流程串起来:

macOS 端口排查知识体系 端口占用排查 lsof -i :端口 查看进程名、PID、状态 netstat -an 快速扫描监听状态 Activity Monitor 图形化查看进程文件 port already in use 方案A:kill -9 进程 方案B:更换端口号 确认进程名后再杀 修改配置或启动参数

4.6 实战场景对比

不同场景下,选哪个工具更顺手?我整理了一个表格:

场景 推荐工具 原因
快速查某个端口被谁占 lsof -i :端口 一行命令,进程名、PID、状态全出来
看系统所有监听端口 netstat -an | grep LISTEN 输出简洁,适合批量扫描
不熟悉命令行的同事排查 Activity Monitor 图形界面,搜索进程名即可
确认进程身份后再杀 lsof + ps aux 先查清楚,避免误杀
我的习惯:日常排查,我90%的情况用 lsof。只有需要快速扫一眼所有端口时,才用 netstat。Activity Monitor 嘛,更多是给团队里不常敲命令的同事用的。

好了,macOS 上的端口排查就这些。记住一个核心思路:先查谁占的,再决定是杀还是换。别一上来就 kill -9,搞不好就把别人的服务干掉了。