- 后端
- 微服务
- 云原生
【免费下载链接】midway
🍔 A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 🌈
应用在服务器上启动失败,是 Node.js 全栈开发者最常遇到的运维场景之一。本文基于 Midway 官方运维文档《服务器启动失败排查》整理成文,系统梳理从"快速定位代码问题"到"逐项排查环境问题"的完整排查链路,并结合仓库源码与部署文档,深入讲解common-error.log日志体系、dist构建产物校验、启动用户权限以及端口冲突等高频故障的根因与解法。读完本文,你将掌握一套在任何 Linux 服务器上都能直接落地的 Midway 启动失败排查方法论。
快速定位代码问题:从进程和日志入手
大多数情况下,我们所说的"启动失败"指的都是服务器环境下的启动失败,下面以 Linux 环境为例展开。逻辑错误、编译错误、配置错误、环境问题,都有可能导致项目无法启动,而排查的核心思路是:先确认现象,再查看日志,最后定位根因。
第 1 步:检查进程是否存在
使用ps aux | grep node检查进程是否存在,并核对进程数量是否正确:
$ ps aux | grep node- 如果没有任何 node 进程,说明应用根本没有启动起来,可能是在启动早期就崩溃了;
- 如果有进程但数量不对(比如 cluster 模式配置了 4 个实例却只起了 1 个),需要检查进程管理工具的配置与系统资源限制;
- 如果进程存在但服务无法访问,则问题可能出在端口监听、防火墙或反向代理配置上。
第 2 步:查看错误日志
打开项目的日志目录,查看common-error.log文件的内容,根据最新的堆栈信息来排查原因。关于日志根目录的详细说明,可以参考 日志文档中的"配置日志根目录"一节。
common-error.log是 Midway 的统一错误日志:所有由 Midway 创建出来的日志对象,都会将错误重复打印一份到该文件中,因此它是启动失败排查时最值得优先查看的文件。
第 3 步:查看启动控制台日志
对于使用 pm2 等进程管理器托管的应用,可以查看启动时的控制台输出,例如:
$ pm2 logs在 pm2 下还可以只查看某个应用的输出:
$ pm2 logs test_app大多数问题都会在日志中发现,请尽可能养成登录机器查看日志的习惯,这是开发者必备的技能。
可能的环境问题:逐项排查
除了代码本身的问题之外,环境问题也可能导致启动失败。这类问题排查起来往往更困难,通常和系统、权限、环境变量、启动参数、网络环境甚至内核本身有关系。下面列举几种常见情况。
1、文件不完整或不是最新
Midway 是 TypeScript 编写的框架,部署到服务器时运行的是编译后的 JavaScript 产物,因此"构建流程没走完"或"文件上传不完整"是最常见的启动失败诱因。
首先,确保项目在部署前执行过以下完整的本地验证流程:
- 使用
npm run dev或者类似命令本地启动并运行成功; - 使用
npm run build已将 TS 文件编译为 JS 文件,在根目录生成出dist目录; - 使用
npm run start在本地使用编译后的 JS 文件执行成功。
然后,检查服务器上的文件与目录结构是否完整:
node_modules目录是否存在(服务器上只安装生产依赖时尤其容易遗漏关键依赖);dist目录以及其中的 JS 文件是否存在,或者为最新(务必确认上传的是最新构建产物,而不是旧包)。
从部署文档可以确认,服务器部署后 Midway只会加载构建后的
dist目录,而本地开发加载的是src目录,两者的baseDir完全不同(详见启动和部署文档)。因此dist缺失或过期,必然导致服务器启动失败。部署时服务器运行必须包含package.json、bootstrap.js、dist、node_modules这些文件或目录。
2、启动用户的权限问题
生产环境一般会使用一个普通账户来执行应用(比如admin账户),而不是使用sudo去部署。这样做的目的是限制应用权限、降低安全风险。排查时关注两点:
- 检查用户是否拥有创建目录、启动 node 的权限;
- 检查项目的服务端日志目录是否有写入的权限。
为什么日志目录权限如此关键?从 日志文档 可知,Midway 在本地开发和服务器部署时的日志输出位置不同:
- 本地的日志根目录为
${app.appDir}/logs/项目名; - 服务器的日志根目录为用户目录
${process.env.HOME}/logs/项目名(Linux/Mac)以及${process.env.USERPROFILE}/logs/项目名(Windows)下,例如/home/admin/logs/example-app。
也就是说,应用启动时需要在当前用户主目录下创建logs/项目名目录并持续写入日志文件。如果该用户没有主目录写入权限,日志系统初始化就会失败,进而导致整个应用无法启动。在 @midwayjs/web 的默认配置 中可以看到,应用日志文件名被设置为midway-web.log,错误日志统一写入logs/${appInfo.pkg.name}/common-error.log,这些文件的创建都依赖启动用户的目录写权限。
3、启动端口冲突
如果你在服务器上启动了多个 Node.js 项目,而它们使用了相同的端口,那么后启动的项目就会抛出端口重复使用的错误(典型如EADDRINUSE)。
排查方法:
# 查看指定端口被哪个进程占用 $ lsof -i :7001 # 或者 $ netstat -tlnp | grep 7001找到占用进程后,要么调整本项目配置的监听端口,要么释放被占用的端口。Midway 默认的 HTTP 端口由使用的 Web 框架决定(如 Koa 默认7001),可通过对应框架的配置项修改端口。
深入理解 common-error.log 与 Midway 日志体系
启动失败排查的核心抓手是日志,因此有必要深入理解 Midway 的日志体系。根据 日志文档,Midway 会在日志根目录创建以下默认文件:
| 文件 | 说明 |
|---|---|
midway-core.log | 框架、组件打印信息的日志,对应coreLogger |
midway-app.log | 应用打印信息的日志,对应appLogger;在@midwayjs/web中,该文件是midway-web.log |
common-error.log | 所有错误的日志(所有 Midway 创建出来的日志,都会将错误重复打印一份到该文件中) |
其中common-error.log是整个排查流程中价值最高的文件,因为它聚合了框架、组件、应用以及请求链路所有日志对象的错误输出,启动阶段的异常堆栈几乎都会出现在这里。
从 web 框架日志实现 的源码注释可以进一步看到,日志对象还支持concentrateError配置项来控制错误日志的写入策略,可选值为:
duplicate:错误同时输出到自身日志文件与common-error.log(默认行为);redirect:错误只重定向到common-error.log;ignore:忽略错误日志的聚合写入。
排查启动失败时,若common-error.log中没有任何内容,也可以反推出应用可能在日志系统初始化之前就崩溃了,此时应优先查看控制台输出或进程启动早期的 stderr。
从部署流程反推启动失败根因
很多服务器启动失败,本质上是部署流程不完整。理解 启动和部署文档 中的部署流程,可以帮助你更快地判断问题属于哪一环节:
整个部署分为几个部分:由于 Midway 是 TypeScript 编写,比传统 JavaScript 代码增加了一个构建步骤。典型的服务器构建流程如下:
$ npm install # 安装开发期依赖 $ npm run build # 构建项目,生成 dist 目录 $ npm prune --production # 移除开发依赖构建完成后,项目结构大致为:
. ├── src ├── dist # Midway 构建产物目录 ├── node_modules # Node.js 依赖包目录 ├── test ├── bootstrap.js # 部署启动文件 ├── package.json └── tsconfig.json服务器上运行时,通过bootstrap.js入口启动(Midway 默认已内置@midwayjs/bootstrap模块):
const { Bootstrap } = require('@midwayjs/bootstrap'); Bootstrap.run();线上使用 pm2 启动的典型命令为(详见 pm2 文档):
$ NODE_ENV=production pm2 start ./bootstrap.js --name midway_app -i 4其中-i 4表示以 cluster 模式启动 4 个实例。部署前后环境有三点明显差异,这些差异往往就是启动失败的来源:
- Node 环境变化:服务器直接使用 node 启动项目,不再依赖
ts-node读取*.ts文件; - 加载目录变化:服务器只加载构建后的
dist目录(baseDir指向dist),本地开发加载src目录; - 环境变量变化:服务器一般设置
NODE_ENV=production,许多库会在该环境下启用缓存、不同的报错处理等行为; - 日志文件位置变化:服务器环境下日志输出到不受项目更新影响的固定目录(如
/home/admin/logs),而不是项目的logs目录。
所以,当你在服务器上遇到启动失败,可以按部署链路逐段自查:本地npm run dev是否成功 →npm run build是否生成最新dist→npm run start(即NODE_ENV=production node bootstrap.js)本地是否成功 → 服务器上文件和目录是否完整 → 启动用户是否有写权限 → 端口是否被占用。任何一环断裂,都可能导致启动失败。
排查启动失败的完整清单
将上述内容整理为一份可直接对照执行的清单:
- 进程层面:
ps aux | grep node确认进程存在且数量正确; - 日志层面:查看
common-error.log最新堆栈(位置参考 配置日志根目录),再查看 pm2 等工具的控制台日志(pm2 logs); - 构建产物:确认
npm run build已在本地生成最新dist,服务器上的dist、node_modules完整且为最新; - 权限层面:确认启动用户(如
admin)有创建目录、启动 node、向${HOME}/logs/项目名写入日志的权限; - 端口层面:
lsof -i :端口或netstat -tlnp确认没有端口冲突; - 环境差异:确认
NODE_ENV、baseDir(srcvsdist)、日志根目录等与本地开发的差异已正确适配。
小结
服务器启动失败排查的核心方法论可以概括为"先日志、后环境":先通过进程状态和common-error.log快速定位代码层问题,再针对构建产物完整性、启动用户权限、端口冲突三大高发环境问题逐项排查。结合 日志体系文档 对日志根目录和默认日志文件的理解,以及 部署流程文档 对构建产物与运行环境差异的把握,绝大多数启动失败都能在几分钟内定位根因。养成登录机器查看日志的习惯,是每一位后端与全栈开发者的必备技能。
- 后端
- 微服务
- 云原生
【免费下载链接】midway
🍔 A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 🌈
相关推荐
Midway 服务器启动失败排查指南:从进程检查到日志定位与常见环境问题
Midway 服务器启动失败排查指南:从进程检查到日志定位与常见环境问题 应用启动失败是 Node.js 服务端项目中最常见的现象——逻辑错误、编译错误、配置错
后端微服务云原生Midway 服务端启动失败排查指南:从进程、日志到环境问题的系统性定位方法
Midway 服务端启动失败排查指南:从进程、日志到环境问题的系统性定位方法 应用启动失败是服务端开发中最常见的现象之一。无论是逻辑错误、编译错误、配置错误,还
后端微服务云原生Midway 服务器启动失败排查实战:从进程、日志到环境问题的完整指南
Midway 服务器启动失败排查实战:从进程、日志到环境问题的完整指南 应用启动失败是 Node.js 服务上线后最常见的现象,逻辑错误、编译错误、配置错误、环
后端微服务云原生
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考