如果本地开发服务器提示端口已被占用,可以使用 macOS 内置的 lsof 命令查找正在监听该 TCP 端口的进程。在“终端”中,运行带有端口号和监听状态筛选条件的 lsof,然后利用报告的 PID 检查该进程,再决定是否终止它。

查找正在监听 TCP 端口的进程

打开“终端”,将 3000 替换为错误信息中显示的端口。按如下方式输入命令;端口号为纯文本,因此无需在终端中进行转义。

lsof -nP -iTCP:3000 -sTCP:LISTEN

lsof 会列出由进程打开的文件,包括网络套接字(Internet socket)。在此命令中,-iTCP:3000 筛选该端口的 TCP 连接,而 -sTCP:LISTEN 将结果缩小为正在等待连接的套接字。-nP 要求 lsof 显示数字地址和端口号,而不是解析名称,这使结果更易于与您搜索的端口进行比对。这些选项记录在 Apple 开源的 macOS lsof 手册中。Apple 的 macOS lsof 手册

输出结果可能如下所示;其中的名称和数字仅为示意,并非来自某台特定 Mac 的真实报告:

COMMAND   PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
node     8421 sam    21u  IPv6 ...          0t0    TCP *:3000 (LISTEN)

COMMAND 代表进程名称,PID 代表其进程 ID。NAME 字段显示本地地址和端口。*:3000 表示通配符地址,而 localhost:3000 或数字形式的环回地址表示环回绑定。通配符监听器可以接受发往多个本地接口的连接;但这本身并不意味着该服务可以通过互联网访问。监听状态筛选条件非常有用,因为一个进程也可能包含涉及该端口的普通客户端连接。

检查 PID 属于什么程序

利用输出中的 PID 向 macOS 的进程列表请求更详细的信息。将 8421 替换为您找到的 PID:

ps -p 8421 -o pid=,ppid=,user=,command=

这将显示进程 ID、父进程 ID、账户名和命令行。该命令行有助于识别该监听器是属于开发服务器、运行时环境还是其他应用程序。lsof 中简短的 COMMAND 值并不总是足以确定具体项目或启动它的应用程序,因此请将更详细的 ps 输出与您预期运行该服务器的“终端”标签页或应用程序进行比对。

如果 lsof 未返回任何行,请检查端口号是否正确,以及应用程序是否仍在运行。服务器可能已退出、可能使用的是 UDP 而非 TCP,或者可能尚未打开其监听套接字。若要检查该端口上的 UDP 套接字,请运行:

lsof -nP -iUDP:3000

UDP 不使用 TCP 的 LISTEN 状态,因此请勿在此查询中添加 -sTCP:LISTEN。如果有结果显示,请以其 COMMAND 和 PID 作为线索,然后如上所述使用 ps 检查该 PID。

如果命令没有显示结果或提示权限错误

在另一个账户下运行的进程可能对您当前的用户不可见。如果您收到与权限相关的提示,或者怀疑套接字归属于其他用户,请使用管理员权限重新运行该 TCP 查询:

sudo lsof -nP -iTCP:3000 -sTCP:LISTEN

“终端”将提示您输入 Mac 账户密码。键入密码时,通常不会显示任何字符;输入完成后按 Return 键即可。利用管理员权限查看结果,然后在采取行动之前确认所属的应用程序。如果该命令仍然没有任何显示,请在端口冲突正在发生时重试:进程状态在报错和查询之间可能会发生变化。

终止正确的应用程序

找到 PID 可以确定一个进程,但这并不能说明终止它是否安全。如果您认得其所有者,请使用启动它的应用程序或“终端”会话来停止该服务器,然后重试您原本的命令。这样可以让应用程序有机会正常关闭。如果您无法确定是什么启动了该进程,请先排查命令行或父 PID,而不是直接终止陌生的系统进程或后台进程。lsof 报告的是当前的套接字归属;它无法说明应用程序为何启动,也无法说明是哪个项目配置选择了该端口。

有关您所安装的 macOS 版本上的命令详情,“终端”可以使用 man lsof 显示其本地手册;按 q 即可退出。Apple 的“终端”使用手册介绍了如何使用 man 查看命令文档。Mac 上的“终端”使用入门

来源