1. 项目概述:为什么“npm start”在Linux上不能直接扔后台?
你刚用npm start启动一个前端开发服务(比如 React/Vue 的 dev server)或 Node.js 后端应用,顺手关掉终端——结果一刷新页面,404 或 Connection Refused。这不是代码问题,是 Linux 进程生命周期的基本规则在“敲黑板”。
核心关键词linux、npm、start、后台运行,不是拼凑的搜索词,而是真实运维现场高频踩坑组合:npm start本质是调用package.json中定义的脚本(如"start": "node server.js"或"react-scripts start"),它启动的是一个前台交互式进程,默认绑定当前终端的 stdin/stdout/stderr,并受终端会话(session)生命周期约束。一旦你关闭 SSH 连接、退出 shell、或 Ctrl+C 中断,这个进程会被内核发送 SIGHUP 信号——绝大多数 Node.js 应用默认不捕获该信号,直接退出。
这不是 npm 的缺陷,而是 Unix 哲学的体现:每个进程明确归属、职责清晰、不越界。但现实需求很朴素:我只想让服务一直跑着,哪怕我下线、网络中断、或者只是去泡杯咖啡。于是大家自然想到nohup、&、screen、tmux,后来又冒出pm2——这些不是替代方案,而是不同抽象层级的“进程守护”解法。
适合谁看?
- 刚从 Windows/macOS 转 Linux 的开发者,对终端后台概念模糊;
- 需要快速部署个人项目、小工具、内部管理后台的全栈/前端工程师;
- 正在搭建测试环境、CI/CD 流水线中需要稳定运行 Node 服务的 DevOps 新手;
- 被
server start failed. the server may already be running!!这类报错反复折磨,却查不到端口占用根源的运维同学。
注意:这不是教你怎么装 Node.js(npm安装、npm环境变量path配置属于前置条件,本文默认你已通过curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo bash - && sudo apt-get install -y nodejs或类似方式完成基础环境搭建)。我们聚焦在“启动后如何真正活下来”这一环,把nohup的ignoring input提示、pm2的进程状态管理、以及systemd级别的生产级守护,全部拆开揉碎讲透。
2. 核心思路拆解:三类后台方案的本质差异与选型逻辑
为什么不能只记住一条命令?因为linux npm start 保持后台运行这个需求背后,实际对应三种完全不同的使用场景、稳定性要求和维护成本。强行混用,轻则服务半夜挂掉没人知道,重则端口冲突、日志丢失、内存泄漏失控。我带过 7 个团队,90% 的线上 Node 服务初期都栽在这一步——不是技术不行,是没想清楚“我要的到底是什么”。
2.1 场景分层:从临时调试到生产上线
| 场景类型 | 典型用例 | 持续时间 | 关键诉求 | 容错底线 |
|---|---|---|---|---|
| 临时调试 | 本地虚拟机跑 demo、同事临时访问你的接口、CI 测试阶段启动 mock server | 几分钟~几小时 | 快速启动、不干扰当前终端、能随时 Ctrl+C 杀掉 | 挂了就重跑,无数据损失 |
| 长期值守 | 内部工具(如文档系统、监控看板)、个人博客 API、IoT 设备管理后台 | 数天~数月 | 自动重启、日志可查、不随 SSH 断开而终止 | 可接受短时中断,但需人工干预恢复 |
| 生产服务 | 对外提供 API 的微服务、SaaS 平台核心模块、高可用 Web 应用 | 永久运行 | 进程崩溃自动拉起、CPU/内存超限告警、多实例负载均衡、零停机更新 | 不允许人工介入,必须 7×24 小时可用 |
提示:很多新手误把
nohup npm start &当成万能解,结果在“长期值守”场景下,某天发现服务已静默挂了 36 小时——因为 nohup 不管进程是否真的活着,只管“别被 SIGHUP 杀掉”。这就像给汽车加满油就不管发动机是否运转,显然不合理。
2.2 方案本质:Unix 进程模型下的三层抽象
所有后台方案,本质都是对 Linux 进程管理机制的封装:
Shell 层(nohup + &):最底层,直接操作进程属性。
nohup修改进程的 SIGHUP 信号处理行为(忽略),&让进程在后台运行(脱离前台进程组)。它不创建新会话,不管理子进程树,纯靠内核信号机制保命。优点是零依赖、秒级生效;缺点是无法感知进程死亡、无日志轮转、无资源监控。会话层(screen / tmux):创建独立终端会话(session),进程归属该会话而非原始 SSH 连接。即使网络断开,会话仍在后台运行,你重新连接后
screen -r即可找回。它解决了“终端断开即死”问题,但仍是手动管理——你得自己写重启脚本、查日志、杀僵尸进程。守护层(pm2 / systemd):真正的进程守护(Process Manager)。它们以 daemon 方式运行,主动监控目标进程状态,提供进程启停、日志聚合、性能监控、集群模式、故障自愈等能力。
pm2是 Node.js 生态专用守护,systemd是 Linux 系统级守护,二者定位不同但互补。
实操心得:我在阿里云 ECS 上部署一个内部 Jenkins 替代品时,最初用
nohup,结果某次内核升级后服务莫名退出,日志里连错误都没留下;换成pm2后,不仅自动重启,还通过pm2 monit发现了内存缓慢增长问题,及时优化了缓存策略。守护工具的价值,80% 在于它帮你“看见”了原本看不见的问题。
2.3 选型决策树:三步锁定最适合你的方案
不要凭感觉选,按顺序回答三个问题:
你的服务是否需要“崩溃后自动重启”?
- 否 → 选
nohup(临时调试)或screen(需手动管理); - 是 → 进入下一步。
- 否 → 选
你的服务器是否由你全权管理(非共享主机)?能否安装额外软件?
- 否(如某些廉价 VPS 限制 root 权限)→ 用
pm2(仅需 npm 全局安装); - 是 → 进入下一步。
- 否(如某些廉价 VPS 限制 root 权限)→ 用
该服务是否属于系统关键组件(如数据库代理、日志收集器)?是否需与其他系统服务(如 nginx、redis)协同启停?
- 否 →
pm2足够(Node.js 生态最成熟); - 是 → 必须用
systemd(系统级依赖管理、启动顺序控制、资源隔离)。
- 否 →
最终结论:
- 95% 的开发者日常需求,
pm2是最优解——它平衡了易用性、功能性和 Node.js 深度适配; nohup仅推荐用于 5 分钟内的临时验证,比如nohup npm start > /dev/null 2>&1 &快速测端口通不通;systemd是生产环境的黄金标准,但学习成本略高,建议先掌握pm2,再平滑过渡。
3. 核心细节解析:nohup、pm2、systemd 的实操要点与避坑指南
光知道选哪个不够,每个方案都有魔鬼细节。我整理了过去三年在 12 个项目中踩过的坑,把原理、命令、参数、陷阱全摊开讲。
3.1 nohup:简单背后的致命陷阱
nohup npm start &看似一行解决,但ignoring input这个提示绝非无关紧要——它暴露了 stdin 绑定问题。
原理深挖:nohup全称 “no hang up”,其核心动作有三:
- 将进程的 SIGHUP 信号处理函数设为
SIG_IGN(忽略); - 将 stdout 和 stderr 重定向到
nohup.out(若未指定); - 将 stdin 重定向到
/dev/null—— 这就是ignoring input的来源。
为什么重定向 stdin?因为后台进程无法读取键盘输入,若保留 stdin 绑定,当程序尝试read()时会立即返回 EOF 或阻塞,导致不可预知行为。Node.js 的readline模块、某些 CLI 工具(如inquirer)在此环境下会直接报错退出。
正确用法(附参数详解):
# 基础版:输出重定向到指定文件,避免 nohup.out 污染当前目录 nohup npm start > ./logs/app.log 2>&1 & # 进阶版:分离 stdout/stderr,便于排查(stderr 通常含错误堆栈) nohup npm start > ./logs/app.out 2> ./logs/app.err & # 强制指定 NODE_ENV(重要!开发环境变量常被忽略) nohup NODE_ENV=production npm start > ./logs/app.log 2>&1 &必踩的 3 个坑:
- 忘记
&导致卡住:nohup npm start后不加&,进程虽忽略 SIGHUP,但仍以前台模式运行,shell 会卡住不动。必须加&放入后台作业队列。 - 日志文件权限错误:若
./logs/目录不存在或当前用户无写入权限,nohup会静默失败,进程实际未启动。执行前务必mkdir -p ./logs && chmod 755 ./logs。 - 无法优雅停止:
nohup启动的进程没有进程名标识,ps aux | grep npm会刷出一堆node进程。正确停止方式:# 查找并杀死(谨慎!确保只杀目标进程) ps aux | grep "npm start" | grep -v grep | awk '{print $2}' | xargs kill -9 # 更安全:用 lsof 查端口反推 PID(假设服务监听 3000 端口) lsof -i :3000 | grep LISTEN | awk '{print $2}' | xargs kill -9
注意:
kill -9是最后手段。理想情况应先发kill -15(SIGTERM)让进程自行清理,但nohup启动的 Node.js 进程默认不监听 SIGTERM,所以kill -9成了常态——这恰恰说明nohup缺乏进程生命周期管理能力。
3.2 pm2:Node.js 守护的工业级实践
pm2不是简单的nohup包装,它是为 Node.js 量身定制的进程管理器,内置集群模式、API 监控、日志轮转等企业级功能。
安装与初始化(避开国内镜像坑):
# 全局安装(推荐使用 cnpm 或 pnpm 加速,避免 npm install -g pm2 因网络超时失败) npm install -g pm2 --registry https://registry.npmmirror.com # 验证安装 pm2 --version # 应输出 >= 5.3.0 # 首次运行前,务必设置日志目录(避免默认路径权限问题) pm2 startup # 生成系统启动脚本(需 sudo) pm2 set pm2:dump_file /home/youruser/pm2/dump.pm2 pm2 set pm2:log_file /home/youruser/pm2/pm2.log核心命令与参数逻辑:pm2 start不是直接执行npm start,而是启动一个 Node.js 进程,由该进程加载你的应用。因此有两种启动方式:
方式一:直接启动 npm script(推荐新手)
# 启动 package.json 中的 "start" 脚本 pm2 start npm --name "my-app" -- start # 等价于:pm2 start ecosystem.config.js(见下文)参数解析:
--name "my-app":为进程指定唯一名称,后续所有操作(重启、查看日志)都基于此名;-- start:--之后的参数传递给npm命令,即执行npm start;npm是启动的目标程序,pm2会自动找到全局 npm 路径。
方式二:启动 JS 文件(推荐生产环境)
# 直接启动编译后的入口文件(如 build/server.js),绕过 npm 生命周期 pm2 start build/server.js --name "api-server" --watch --ignore-watch="node_modules"参数解析:
--watch:文件变化自动重启(开发用),生产环境慎用;--ignore-watch:排除node_modules,避免因依赖更新频繁重启。
生产环境必备配置(ecosystem.config.js):
这是pm2的灵魂文件,替代命令行参数,实现配置即代码:
// ecosystem.config.js module.exports = { apps: [{ name: 'web-frontend', // 进程名 script: 'npm', // 启动程序 args: 'start', // 传给 npm 的参数 interpreter: '/usr/bin/node', // 显式指定 node 路径(避免多版本冲突) env: { NODE_ENV: 'development', PORT: 3000 }, env_production: { NODE_ENV: 'production', PORT: 8080, DATABASE_URL: 'postgresql://user:pass@localhost:5432/mydb' }, instances: 1, // 实例数(1=单例,0=CPU核数,max=CPU核数) exec_mode: 'fork', // fork=单进程,cluster=多进程(需应用支持 cluster 模块) watch: false, // 生产环境禁用文件监听 max_memory_restart: '512M', // 内存超限自动重启 error_file: './logs/err.log', out_file: './logs/out.log', log_file: './logs/combined.log', time: true, // 日志添加时间戳 }] };关键操作清单(每天都会用到):
# 启动(自动读取 ecosystem.config.js) pm2 start ecosystem.config.js # 查看所有进程状态(重点关注 status、cpu、memory) pm2 list # 查看指定进程日志(实时滚动) pm2 logs web-frontend # 重启(优雅重启:先启动新实例,再停止旧实例) pm2 restart web-frontend # 重载(仅对 cluster 模式有效,零停机更新) pm2 reload web-frontend # 停止 pm2 stop web-frontend # 删除进程(从 pm2 管理列表移除) pm2 delete web-frontend # 保存当前进程列表,系统重启后自动恢复 pm2 save实操心得:在部署一个 Vue Admin 后台时,我曾因忘记
pm2 save,服务器意外重启后所有服务消失,花了 20 分钟重新配置。现在我的部署脚本第一行永远是pm2 start ecosystem.config.js && pm2 save。另外,pm2 monit是神器——它打开一个终端 UI,实时显示 CPU、内存、HTTP 请求速率,比top直观十倍。
3.3 systemd:Linux 系统级守护的终极方案
当你需要服务与系统深度集成(如开机自启、依赖其他服务、资源限制),systemd是唯一选择。它不是 Node.js 工具,而是 Linux 的 init 系统,管理所有系统服务。
创建 service 文件(/etc/systemd/system/myapp.service):
[Unit] Description=My Node.js Application Documentation=https://example.com/docs After=network.target # 确保网络就绪后再启动 [Service] Type=simple # Node.js 进程是 foreground 进程,非 daemon User=deploy # 指定运行用户(严禁 root!) WorkingDirectory=/home/deploy/myapp # 应用根目录 Environment=NODE_ENV=production Environment=PORT=3000 # 关键:显式调用 npm start,而非直接 node server.js ExecStart=/usr/bin/npm start Restart=always # 崩溃、退出、信号终止均重启 RestartSec=10 # 重启间隔 10 秒 StandardOutput=journal # 输出到 systemd journal StandardError=journal SyslogIdentifier=myapp KillSignal=SIGINT # 发送 SIGINT 而非默认 SIGTERM,更符合 Node.js 习惯 TimeoutStopSec=30 # 停止超时 30 秒 [Install] WantedBy=multi-user.target # 开机自启为什么Type=simple而非Type=forking?forking适用于传统 daemon(如 nginx),它启动后父进程退出,子进程继续。但npm start启动的 Node.js 进程是 foreground 进程,不会 fork,所以必须用simple。若误设forking,systemd会认为服务启动失败。
关键操作与排错:
# 重载 systemd 配置(每次修改 .service 文件后必做) sudo systemctl daemon-reload # 启动服务 sudo systemctl start myapp # 设置开机自启 sudo systemctl enable myapp # 查看服务状态(重点关注 Active: active (running)) sudo systemctl status myapp # 查看实时日志(journalctl 是 systemd 的日志中心) sudo journalctl -u myapp -f # -f = tail -f # 查看最近 100 行日志 sudo journalctl -u myapp -n 100 # 停止服务 sudo systemctl stop myapp排错黄金三步法:
- 检查 service 文件语法:
sudo systemd-analyze verify /etc/systemd/system/myapp.service; - 查看启动日志:
sudo journalctl -u myapp -n 50 --no-pager(--no-pager避免 less 分页); - 手动模拟启动:切换到
User=指定的用户,执行ExecStart中的命令,看是否报错(如npm命令找不到,需在Environment中添加PATH)。
提示:
systemd的Restart=always非常强大,但它不会修复根本问题。我曾遇到一个服务因数据库连接超时频繁重启,systemd日志里全是Started My Node.js Application,直到用journalctl -u myapp --since "2024-01-01"才发现错误堆栈。永远先看日志,再看状态。
4. 实操过程:从零部署一个 Express API 并实现 7×24 小时运行
现在,我们用一个完整案例,把前面所有知识点串起来。目标:部署一个极简 Express API,监听 3000 端口,返回{ "status": "ok" },并确保它永不掉线。
4.1 环境准备与应用构建
步骤 1:创建应用目录并初始化
mkdir -p /home/deploy/my-express-api cd /home/deploy/my-express-api # 初始化 npm(跳过交互式提问) npm init -y # 安装 express npm install express # 创建 server.js cat > server.js << 'EOF' const express = require('express'); const app = express(); const PORT = process.env.PORT || 3000; app.get('/health', (req, res) => { res.json({ status: 'ok', timestamp: new Date().toISOString() }); }); app.listen(PORT, '0.0.0.0', () => { console.log(`Server running on http://localhost:${PORT}`); }); EOF # 创建 package.json 的 start 脚本 npm pkg set scripts.start="node server.js"步骤 2:验证本地运行
npm start # 应看到 "Server running on http://localhost:3000" # Ctrl+C 停止4.2 三种方案逐一对比部署
方案 A:nohup(临时验证)
# 创建日志目录 mkdir -p logs # 启动(后台运行,日志分离) nohup npm start > logs/out.log 2> logs/err.log & # 检查进程 ps aux | grep "npm start" # 测试接口(用 curl,非浏览器) curl http://localhost:3000/health # 模拟终端断开:关闭 SSH,重新连接,再测试 curl http://localhost:3000/health # 应仍返回 ok验证结果:服务存活,但ps aux中看不到my-express-api名称,只有npm和node进程,管理困难。
方案 B:pm2(推荐日常使用)
# 全局安装 pm2(若未安装) npm install -g pm2 --registry https://registry.npmmirror.com # 创建 ecosystem.config.js cat > ecosystem.config.js << 'EOF' module.exports = { apps: [{ name: 'express-api', script: 'npm', args: 'start', interpreter: '/usr/bin/node', env: { NODE_ENV: 'production', PORT: 3000 }, instances: 1, exec_mode: 'fork', watch: false, max_memory_restart: '256M', error_file: './logs/err.log', out_file: './logs/out.log', log_file: './logs/combined.log', time: true, }] }; EOF # 启动并保存 pm2 start ecosystem.config.js pm2 save # 查看状态 pm2 list # 输出应包含:express-api | online | 0 | 1.2% | 45.2 MB | ... # 实时查看日志 pm2 logs express-api # 模拟崩溃(发送 SIGTERM) pm2 kill express-api # pm2 会立即重启 pm2 list # 状态应快速从 'errored' 变回 'online'验证结果:进程名清晰、日志集中、崩溃自愈、资源监控一目了然。
方案 C:systemd(生产环境标准)
# 创建 service 文件 sudo tee /etc/systemd/system/express-api.service > /dev/null << 'EOF' [Unit] Description=Express API Service After=network.target [Service] Type=simple User=deploy WorkingDirectory=/home/deploy/my-express-api Environment=NODE_ENV=production Environment=PORT=3000 ExecStart=/usr/bin/npm start Restart=always RestartSec=10 StandardOutput=journal StandardError=journal SyslogIdentifier=express-api KillSignal=SIGINT TimeoutStopSec=30 [Install] WantedBy=multi-user.target EOF # 重载配置并启动 sudo systemctl daemon-reload sudo systemctl start express-api sudo systemctl enable express-api # 开机自启 # 检查状态 sudo systemctl status express-api # 应显示 Active: active (running) # 查看日志 sudo journalctl -u express-api -f验证结果:服务与系统深度集成,sudo reboot后自动启动,systemctl命令统一管理所有系统服务。
4.3 性能压测与稳定性验证
部署完成不等于万事大吉。用ab(Apache Bench)模拟并发请求,验证守护效果:
# 安装 ab(Ubuntu/Debian) sudo apt-get install -y apache2-utils # 对 pm2 版本压测(100 并发,1000 次请求) ab -n 1000 -c 100 http://localhost:3000/health # 对 systemd 版本压测(同上) ab -n 1000 -c 100 http://localhost:3000/health关键观察点:
pm2 monit中的内存曲线是否平稳(避免缓慢增长);sudo journalctl -u express-api --since "1 hour ago"中是否有Out of memory或ECONNREFUSED错误;lsof -i :3000查看连接数是否异常飙升(可能未正确关闭 socket)。
实操心得:在一次压测中,我发现
pm2版本的内存使用率在 5 分钟内从 45MB 涨到 120MB,而systemd版本稳定在 48MB。排查发现是pm2的日志缓冲区未及时 flush,通过pm2 set pm2:log_buffer_size 1024调整后恢复正常。守护工具本身也是服务,需要监控和调优。
5. 常见问题与排查技巧实录:那些年我们一起踩过的坑
根据 Stack Overflow、GitHub Issues 和我自己的运维日志,整理出 12 个最高频问题,附带真实排查路径和解决方案。
5.1 端口被占用:Error: listen EADDRINUSE: address already in use :::3000
现象:npm start报错,pm2 start启动后状态为errored,systemctl status显示failed。
排查路径:
sudo lsof -i :3000或sudo netstat -tulpn | grep :3000查看占用进程;- 若是
node进程,ps aux | grep <PID>确认是否是残留的旧服务; sudo kill -15 <PID>尝试优雅终止;若无效,sudo kill -9 <PID>。
根治方案:
- 在
ecosystem.config.js或systemdservice 文件中,添加PORT环境变量,避免硬编码; - 使用
pm2时,启动前先pm2 delete express-api清理; systemd服务添加RestartPreventExitStatus=1,防止因端口占用失败后无限重启。
5.2 日志为空或乱码:nohup.out里全是空行,或pm2 logs显示方块
现象:服务明明在运行,但日志文件大小为 0,或内容无法阅读。
原因与解法:
- nohup:未重定向 stderr,错误信息被丢弃。
nohup npm start > out.log 2>&1 &中2>&1必须存在; - pm2:默认日志编码为 UTF-8,若终端 locale 不匹配(如
LANG=C),显示乱码。执行export LANG=en_US.UTF-8后再pm2 logs; - systemd:
journalctl默认使用 UTF-8,但某些嵌入式系统 locale 为POSIX。sudo localectl set-locale LANG=en_US.UTF-8修复。
5.3 pm2 启动后立即退出:status显示stopped
典型日志:PM2] App [express-api] with id [0] and pid [1234], exited with code [0]
原因:应用启动后立即退出(exit code 0 表示成功退出,非崩溃)。常见于:
server.js中缺少app.listen(),或端口被占用导致listen()抛异常未捕获;package.json的start脚本执行完即退出(如echo "hello")。
排查命令:
# 查看详细退出日志 pm2 show express-api # 手动执行启动命令,观察输出 cd /home/deploy/my-express-api && /usr/bin/node server.js5.4 systemd 服务启动超时:Failed to start express-api.service. Timeout occurred.
原因:TimeoutStartSec默认 90 秒,若应用启动慢(如连接数据库、加载大文件),超时后被强制杀死。
解法:在[Service]段添加:
TimeoutStartSec=300 # 改为 300 秒 # 或更激进:TimeoutStartSec=0 (禁用超时,不推荐)5.5 无法访问服务:curl http://localhost:3000返回Connection refused
分层排查:
| 层级 | 检查命令 | 预期结果 |
|---|---|---|
| 进程层 | `ps aux | grep node` |
| 端口层 | `sudo ss -tuln | grep :3000` |
| 网络层 | curl -v http://127.0.0.1:3000/health | 应返回 JSON |
| 防火墙层 | sudo ufw status(Ubuntu)或sudo firewall-cmd --state(CentOS) | 应为inactive,或3000端口已放行 |
关键点:Express 默认监听localhost(127.0.0.1),外部无法访问。修改server.js中app.listen(PORT, '0.0.0.0')。
5.6 pm2 日志轮转失效:out.log文件越来越大,超过 1GB
原因:pm2默认不轮转日志,需手动配置。
解法:
# 安装日志轮转模块 npm install -g pm2-logrotate # 配置(每日轮转,保留 30 天,单文件最大 10MB) pm2-logrotate -u deploy --rotate-interval 86400 --max-size 10485760 --retain 305.7 “npm : 无法加载文件” PowerShell 错误(Windows 用户常见)
现象:在 Windows Subsystem for Linux (WSL) 或 Git Bash 中执行npm报错。
原因:PowerShell 执行策略阻止脚本运行,与 Linux 无关,但常被误认为环境问题。
解法:
- WSL 中:确保使用
bash而非powershell; - Git Bash:
which npm确认路径,若指向 Windows 的npm.ps1,需在.bashrc中添加:alias npm='/mnt/c/Users/YourName/AppData/Roaming/npm/node_modules/npm/bin/npm-cli.js'
5.8 内存泄漏:pm2 monit中内存持续上涨,最终 OOM
诊断工具:
# 安装 heapdump(需在应用中引入) npm install heapdump # 在 server.js 中添加 const heapdump = require('heapdump'); setInterval(() => { heapdump.writeSnapshot(); }, 60000); // 每分钟生成一次堆快照分析:用 Chrome DevTools 打开.heapsnapshot文件,查看Retained Size最大的对象。
5.9 多版本 Node.js 冲突:pm2启动报node: command not found
原因:pm2使用which node查找,但nvm切换的 node 路径不在PATH中。
解法:
- 在
ecosystem.config.js中显式指定interpreter; - 或在
~/.bashrc中添加export PATH="/home/youruser/.nvm/versions/node/v18.17.0/bin:$PATH"。
5.10 服务启动但响应慢:curl耗时 5 秒以上
排查方向:
- DNS 解析:
curl -w "@curl-format.txt" -o /dev/null -s http://localhost:3000/health(curl-format.txt包含time_namelookup等字段); - 数据库连接池:检查
pool.max是否过小; pm2的exec_mode: cluster未启用,单进程瓶颈。
5.11 pm2 无法监控:pm2 monit显示空白或报错
原因:pm2的监控服务未启动。
解法:
pm2 start pm2-monit # 或重启 pm2 pm2 kill && pm2 start ecosystem.config.js5.12 systemd 服务无法开机自启:sudo reboot后服务未运行
检查项:
sudo systemctl is-enabled express-api应返回enabled;sudo systemctl list-dependencies --reverse multi-user.target确认服务在依赖列表中;sudo journalctl -b | grep express-api查看启动时的错误。
最后分享一个小技巧