跳至正文

PM2 生产环境配置与维护指南

目录

  1. 为什么使用 ecosystem.config.js?
  2. 配置示例与参数详解
  3. PM2 日志管理详解
  4. 常见问题与解决方案

1. 为什么使用 ecosystem.config.js?

1.1 什么是 ecosystem.config.js?

ecosystem.config.js 是 PM2 的配置文件,用于定义和管理多个服务进程。

1.2 不用配置文件的问题

启动方式 问题
pm2 start npm -- ... 命令复杂,容易写错
pm2 start app.js -- --args 参数难以管理
多个服务分别启动 需要记多个命令,容易遗漏

1.3 使用配置文件的优势

优势 说明
集中管理 所有服务配置在一个文件
一键启动 pm2 start ecosystem.config.js 启动所有服务
版本控制 配置可以提交到 Git,团队共享
环境变量 方便配置敏感信息
统一日志 日志路径统一管理
自动重启 崩溃自动恢复

1.4 潜在缺点

缺点 解决方案
敏感信息泄露 使用 .env 文件,不提交到 Git
配置复杂 参考本文档

2. 配置示例与参数详解

2.1 实际配置示例

module.exports = {
  apps: [
    // MongoDB 数据库服务
    {
      name: 'mongodb',
      script: '/usr/bin/mongod',
      args: '--dbpath /data/gamedb --port 27017 --bind_ip 127.0.0.1 --logpath /data/gamedb/mongodb.log --logappend --systemLog.rotation.size 50000000',
      cwd: '/',
      instances: 1,
      autorestart: true,
      watch: false,
    },

    // 游戏服务器
    {
      name: 'game-server',
      script: './build/gameServer.js',
      cwd: '/home/prod/game_server',
      instances: 1,
      autorestart: true,
      watch: false,
      max_memory_restart: '1G',
      env: {
        NODE_ENV: 'production'
      },
      error_file: './logs/game-server-error.log',
      out_file: './logs/game-server-out.log',
      log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
      merge_logs: true
    },

    // 管理后台
    {
      name: 'game-admin',
      script: './build/adminServer.js',
      cwd: '/home/prod/game_server',
      instances: 1,
      autorestart: true,
      watch: false,
      max_memory_restart: '1G',
      env: {
        NODE_ENV: 'production'
      },
      error_file: './logs/game-admin-error.log',
      out_file: './logs/game-admin-out.log',
      log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
      merge_logs: true
    }
  ]
};

2.2 参数详解

基础参数

参数 说明 示例值
name 进程名称,用于标识 game-server
script 启动脚本路径 ./build/gameServer.js
cwd 工作目录 /home/prod/game_server
args 启动参数(仅对脚本生效) --port 27017

进程管理参数

参数 说明 示例值
instances 启动实例数量 1
autorestart 崩溃时自动重启 true
watch 监听文件变化(生产环境必须 false false
max_memory_restart 内存超过阈值自动重启 '1G'

环境变量参数

参数 说明 示例值
env 环境变量对象 { NODE_ENV: 'production' }
NODE_ENV 运行环境 production / development

注意:敏感信息(WX_APPID、WX_SECRET)不写入此文件,而是通过 .env 文件或命令行传入。

日志参数

参数 说明 示例值
error_file 错误日志路径 ./logs/error.log
out_file 标准输出日志路径 ./logs/out.log
log_date_format 日志时间格式 'YYYY-MM-DD HH:mm:ss Z'
merge_logs 多实例合并日志 true

2.3 启动方式

# 方式1:使用 .env 文件(推荐)
cd /home/prod/game_server
pm2 start ecosystem.config.js

# 方式2:命令行传入环境变量
cd /home/prod/game_server
WX_APPID=xxx WX_SECRET=xxx pm2 start ecosystem.config.js

# 方式3:指定环境
pm2 start ecosystem.config.js --env production

3. PM2 日志管理详解

3.1 什么是 pm2-logrotate?

pm2-logrotate 是 PM2 官方提供的日志轮转插件,用于自动管理 PM2 进程产生的日志文件。

3.2 为什么需要 pm2-logrotate?

问题 说明
磁盘空间 日志文件会不断增长,不管理会导致磁盘满
性能下降 日志文件过大会影响写入性能
难以查看 大文件难以打开和搜索

没有日志轮转的后果

  • 日志文件从 MB 增长到 GB
  • 最终磁盘写满 → 服务崩溃
  • 无法生成新日志 → 无法排查问题

3.3 工作原理

# 安装前
game-server-out.log  (无限增长 -> 1GB -> 10GB)

# 安装后
game-server-out.log     (当前正在写入)
game-server-out.log.1  (轮转后的旧文件)
game-server-out.log.2  (更早的旧文件)
...

当日志文件达到配置大小或时间条件时,pm2-logrotate 会:

  1. 关闭当前日志文件
  2. 创建新日志文件继续写入
  3. 压缩或删除旧的日志文件

3.4 安装和配置命令

# 1. 安装 pm2-logrotate 插件
pm2 install pm2-logrotate

# 2. 配置单个日志文件最大大小(超过后轮转)
pm2 set pm2-logrotate:max_size 10M

# 3. 配置保留的文件数量(超过数量会删除旧的)
pm2 set pm2-logrotate:retain 5

# 4. 是否压缩旧文件(节省空间)
pm2 set pm2-logrotate:compress true

# 5. 配置轮转时间(可选,默认每天)
pm2 set pm2-logrotate:rotateInterval '0 3 * * *'

# 6. 查看当前配置
pm2 set

3.5 参数详解

参数 说明 示例值
max_size 单个日志文件最大大小 10M (10MB)
retain 保留的文件数量 5
compress 是否压缩旧文件 true / false
rotateInterval 轮转时间cron表达式 0 3 * * * (每天凌晨3点)

3.6 手动执行轮转

# 手动触发一次轮转
pm2 reloadLogs

# 查看日志文件
ls -lh ~/.pm2/logs/

3.7 注意事项

注意事项 说明
只对 PM2 捕获的日志有效 对 MongoDB 等第三方进程无效
需要安装插件 pm2 install pm2-logrotate
配置后立即生效 不需要重启 PM2

4. 常见问题与解决方案

4.1 查看日志的常用命令

在排查问题前,首先需要查看日志。以下是常用命令:

# 查看所有服务的日志(实时)
pm2 logs

# 查看指定服务的日志
pm2 logs game-server

# 只看错误日志
pm2 logs game-server --err

# 查看最近 50 行日志
pm2 logs --lines 50

# 实时查看错误日志
pm2 logs game-server --err --lines 20

# 查看日志文件(适用于已轮转的日志)
cat ~/.pm2/logs/game-server-out.log
tail -f ~/.pm2/logs/game-server-out.log

# 查看日志文件大小
ls -lh ~/.pm2/logs/

问题 2:端口被占用

错误

Error: listen EADDRINUSE: address already in use :::3000

解决

# 查看占用端口的进程
lsof -i:3000

# 停止占用进程
kill -9 

# 或查看 PM2 进程
pm2 list
pm2 delete <进程名>

问题 3:进程启动失败

错误

Process crashed with code '1'

解决

# 查看错误日志
pm2 logs <进程名>

# 常见原因:
# 1. 缺少依赖 - 重新安装 npm install
# 2. 启动命令错误 - 检查 script 和 args
# 3. 权限不足 - 检查文件权限
# 4. 环境变量缺失 - 检查 .env 文件

问题 4:内存持续增长

错误

PM2  memory usage: 1.2GB

解决

# 检查内存使用
pm2 monit

# 配置自动重启
max_memory_restart: '1G'

# 查看内存泄漏
# 1. 重启进程
pm2 restart <进程名>
# 2. 观察内存增长趋势

问题 5:进程不断重启

原因

  • 进程崩溃后立即重启
  • 配置了 autorestart: true

解决

# 查看重启日志
pm2 logs --err --lines 50

# 临时禁用自动重启
pm2 stop <进程名>

# 修复问题后重新启动
pm2 restart <进程名>

问题 6:服务器重启后服务没有自动启动

解决

# 保存当前进程列表
pm2 save

# 如果还是不行,检查 startup 脚本
pm2 startup
# 按照输出命令执行

问题 7:环境变量不生效

原因

  • .env 文件位置不对
  • NODE_ENV 判断错误

解决

# 检查 .env 文件位置(必须在 cwd 目录下)
# 当前配置 cwd: '/home/prod/game_server'
# 所以 .env 必须在 /home/prod/game_server/.env

# 检查环境变量
pm2 show <进程名>
# 查看 env 字段

# 手动传入测试
NODE_ENV=production pm2 start ecosystem.config.js

问题 8:日志文件过大

原因

  • 没有安装 pm2-logrotate
  • pm2-logrotate 未正确配置

解决

# 1. 安装 pm2-logrotate
pm2 install pm2-logrotate

# 2. 配置参数
pm2 set pm2-logrotate:max_size 10M   # 单个日志最大 10MB
pm2 set pm2-logrotate:retain 5        # 保留 5 个文件
pm2 set pm2-logrotate:compress true    # 压缩旧文件

# 3. 查看配置
pm2 set

# 4. 手动触发轮转测试
pm2 reloadLogs

问题 9:MongoDB 启动失败

错误

mongod: error: '/data/gamedb' does not exist

解决

# 创建数据目录
sudo mkdir -p /data/gamedb

# 设置权限
sudo chown -R $(whoami) /data/gamedb

# 重新启动
pm2 restart mongodb

附录:快速参考命令

# 启动所有服务
pm2 start ecosystem.config.js

# 查看进程状态
pm2 list
pm2 status

# 查看日志
pm2 logs                    # 所有日志
pm2 logs game-server          # 指定服务日志

# 重启/停止
pm2 restart all            # 重启所有
pm2 stop all               # 停止所有
pm2 delete all             # 删除所有进程

# 保存配置(服务器重启后自动启动)
pm2 save

# 查看详细信息
pm2 show game-server

# 监控资源
pm2 monit

# 安装日志轮转
pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 10M
pm2 set pm2-logrotate:retain 5

标签:

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注