问题
当你尝试重启一个 Node 应用时,上一个应用没有正确关闭,你可能会看到一个“listen EADDRINUSE: address already in use”错误,例如:
1 | ⇒ npm start |
问题背后的原因
process.on('exit', ...)
不会在进程崩溃或被杀死时调用。它只在事件循环结束时调用,因为 server.close()
会结束事件循环(它仍然必须等待当前运行的堆栈),所以将其放在 exit 事件中是没有意义的。
译者注:有时候直接关闭 vscode 会导致进程没有正确关闭,这时候也可能会出现这个问题。
解决方案
该应用程序的正确修复是
- 在
server.listen()
之前检查端口是否已经被占用 - 在崩溃时,可以使用
process.on('uncaughtException', ..)
进行处理。 - 在
kill
操作上,可以使用process.on('SIGTERM', ..)
进行处理。
当出现 EADDRINUSE 问题时,为了解决它,你需要手动终止该进程。为此,你需要找到进程的进程 ID(PID)。
手动杀死进程
Mac/Linux
找到与该端口关联的进程 ID(PID)
1 | $ lsof -i tcp:3000 |
这将返回使用该端口的任何进程的详细信息,包括PID。然后可以使用以下命令杀死该进程:
1 | $ kill -9 44475 |
请注意,-9
选项强制终止进程而不考虑其当前状态,并立即使其退出。当需要强制关闭一个已经挂起或占据端口的进程时,通常需要使用此选项。
如果你遇到权限问题,请尝试在命令前加上sudo。例如:
1 | sudo kill -9 44475 |
Windows
解决方案 1:任务管理器
打开“任务管理器”应用程序 (taskman.exe),从进程或服务选项卡根据 PID 列进行排序。要显示 PID 列,请右键单击标头行并从列表中选择 PID。右键单击要停止的进程,然后选择“结束任务”
解决方案 2:命令行
以管理员身份打开CMD(命令提示符)窗口,通过导航到 开始 > 运行 > 输入cmd > 右键单击“命令提示符”
,然后选择“以管理员身份运行”打开 。
可以使用命令提示符来查找与特定端口相关的进程ID。在管理员模式下打开CMD窗口,然后使用” netstat “命令来获取所有处于活动状态的端口以及占用者的进程ID。以下是要使用的完整命令:
1 | $ netstat -ano|findstr "PID :3000" |
其中 -a
选项显示所有正在使用的端口(而不仅仅是与当前用户相关的端口)。-n
选项停止主机名查询(这需要很长时间)。-o
选项列出负责端口活动的进程 ID。最后,findstr
命令匹配包含 PID 字符串的标题行,并查找指定的端口。例如, PID :3000
。
然后终止此进程(/f
是强制):
1 | $ taskkill /pid 18264 /f |
原文地址:How to kill server when seeing “EADDRINUSE: address already in use”
原文作者:BChen
译文出自:紫升翻译计划