You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu Server 20.04下Node.js+PM2集群模式启动异常排查

我之前在Ubuntu 20.04上也碰到过一模一样的问题,直接用node server.js正常,但PM2集群模式就不停重启报EADDRINUSE,后来排查下来是几个常见原因,给你几个可行的解决方案:

1. 检查Node.js版本兼容性

Ubuntu 20.04自带的Node.js版本和18.04的默认版本有差异,PM2的集群模式对某些Node版本的端口监听逻辑处理有变化。先看看你当前的Node版本:

node -v

如果是v14及以上,大概率是你的服务代码没有适配集群模式的端口共享机制——默认情况下,PM2集群模式会让主进程创建监听句柄,子进程复用它,但如果你的代码里每个进程都自己去绑定3000端口,就会冲突。

2. 修改服务代码适配集群模式

如果你的server.js里是直接写app.listen(3000),那在集群模式下每个子进程都会尝试绑定3000端口,必然报错。可以改成两种方式:

方式一:让PM2自动处理集群逻辑(推荐)

把你的Express app导出,只在直接运行时才启动监听:

const express = require('express');
const app = express();

// 你的路由和中间件逻辑
app.get('/', (req, res) => {
  res.send('API is running');
});

// 只有当直接执行server.js时才启动监听
if (!module.parent) {
  app.listen(3000, () => {
    console.log(`Server running on port 3000`);
  });
}

// 导出app供PM2集群模式复用
module.exports = app;

这样PM2启动集群时,会自动创建共享的监听句柄,子进程不需要自己绑定端口。

方式二:手动处理集群逻辑

如果你想自己控制集群行为,可以用Node.js内置的cluster模块:

const cluster = require('cluster');
const os = require('os');
const app = require('./your-app'); // 假设你的app在单独文件里
const http = require('http');

const numCPUs = os.cpus().length;

if (cluster.isPrimary) {
  console.log(`主进程 ${process.pid} 启动`);
  // 衍生对应CPU核心数的子进程
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker) => {
    console.log(`子进程 ${worker.process.pid} 退出,重新启动...`);
    cluster.fork();
  });
} else {
  // 子进程复用主进程的监听句柄
  http.createServer(app).listen(3000);
  console.log(`子进程 ${process.pid} 启动,监听端口3000`);
}
3. 更新PM2到最新版本

旧版本PM2和Ubuntu 20.04的Node.js可能存在兼容性问题,先更新PM2:

npm install pm2@latest -g
pm2 update

更新后先删掉旧的PM2进程,再重新启动:

pm2 delete server
pm2 start server.js --name server -i max
4. 排查隐藏的端口占用进程

虽然你确认没有其他Node服务,但可能存在僵尸进程占用3000端口,用以下命令检查:

sudo lsof -i :3000

或者:

sudo ss -tulpn | grep :3000

如果发现有进程占用,直接杀掉:

sudo kill -9 <进程PID>

然后再启动PM2。

5. 强制监听IPv4

Ubuntu 20.04默认优先IPv6,可能导致Node.js尝试绑定IPv6的::地址时出现冲突。可以强制服务只监听IPv4:

// 在listen时指定0.0.0.0
app.listen(3000, '0.0.0.0', () => {
  console.log(`Server listening on 0.0.0.0:3000`);
});

或者启动PM2时设置环境变量强制IPv4优先:

PM2_NODE_OPTIONS="--dns-result-order=ipv4first" pm2 start server.js --name server -i max

内容的提问来源于stack exchange,提问作者Satyam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 20:27:46