[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"menus-public":3,"blog-10035":83,"blog-10035-comments":92},[4,15,43,66],{"id":5,"title":6,"link":7,"icon":8,"target":9,"sort_order":10,"is_active":11,"parent_id":12,"created_at":13,"children":14},10001,"首页","\u002F","","_blank",0,true,null,"2026-04-04T12:03:45",[],{"id":16,"title":17,"link":18,"icon":8,"target":19,"sort_order":20,"is_active":11,"parent_id":12,"created_at":21,"children":22},10038,"墨言博客","\u002Fblog","_self",1,"2026-10-30T23:08:14",[23,29,36],{"id":24,"title":25,"link":26,"icon":8,"target":19,"sort_order":20,"is_active":11,"parent_id":16,"created_at":27,"children":28},10039,"技术前沿","\u002Fblog?category=10001","2026-10-30T23:10:46",[],{"id":30,"title":31,"link":32,"icon":8,"target":19,"sort_order":33,"is_active":11,"parent_id":16,"created_at":34,"children":35},10042,"生活随笔","\u002Fblog?category=20007",2,"2026-10-30T23:55:19",[],{"id":37,"title":38,"link":39,"icon":8,"target":19,"sort_order":40,"is_active":11,"parent_id":16,"created_at":41,"children":42},10043,"旅游日记","\u002Fblog?category=20006",3,"2026-10-31T00:00:11",[],{"id":33,"title":44,"link":45,"icon":8,"target":19,"sort_order":33,"is_active":11,"parent_id":12,"created_at":46,"children":47},"新闻中心","\u002Fnews","2026-10-24T19:09:40",[48,54,60],{"id":49,"title":50,"link":51,"icon":8,"target":19,"sort_order":20,"is_active":11,"parent_id":33,"created_at":52,"children":53},10046,"产品动态","\u002Fnews?category=20010","2026-10-31T00:17:38",[],{"id":55,"title":56,"link":57,"icon":8,"target":19,"sort_order":33,"is_active":11,"parent_id":33,"created_at":58,"children":59},10047,"新闻热点","\u002Fnews?category=20009","2026-10-31T00:17:55",[],{"id":61,"title":62,"link":63,"icon":8,"target":19,"sort_order":40,"is_active":11,"parent_id":33,"created_at":64,"children":65},10045,"公司动态","\u002Fnews?category=20008","2026-10-31T00:17:11",[],{"id":67,"title":68,"link":69,"icon":8,"target":19,"sort_order":67,"is_active":11,"parent_id":12,"created_at":46,"children":70},4,"精彩视频","\u002Fvideo",[71,77],{"id":72,"title":73,"link":74,"icon":8,"target":19,"sort_order":10,"is_active":11,"parent_id":67,"created_at":75,"children":76},13,"活动记录","\u002Fvideo?category=6","2026-10-25T21:04:39",[],{"id":78,"title":79,"link":80,"icon":8,"target":19,"sort_order":20,"is_active":11,"parent_id":67,"created_at":81,"children":82},11,"产品展示","\u002Fvideo?category=5","2026-10-25T21:02:59",[],{"id":84,"category_id":5,"title":85,"author":8,"summary":86,"cover":87,"content":88,"tags":8,"seo_title":8,"seo_description":8,"seo_keywords":8,"og_image":8,"views":89,"comment_count":10,"is_top":90,"is_published":11,"created_at":91},10035,"MP2命令使用教程","PM2 是一个基于 Node.js 的守护进程管理器，用于管理并保持应用程序在线运行。它提供了简单直观的命令行接口，支持进程守护、集群模式、日志管理、开机自启等生产级功能，是 Node.js 应用部署的事实标准工具。-","\u002Fstatic\u002Fuploads\u002Fblogs\u002F1792157541399-888073881.jpg","# PM2 使用教程\n\n## 目录\n\n- [[#1.PM2简介|1.PM2简介]]\n- [[#2.环境要求|2. 环境要求]]\n- [[#3.安装|3. 安装]]\n  - [[#3.1Linux\u002FmacOS|3.1 Linux\u002FmacOS]]\n  - [[#3.2Windows|3.2 Windows]]\n  - [[#3.3Docker中使用|3.3 Docker 中使用]]\n- [[#4.快速上手|4. 快速上手]]\n- [[#5.核心命令|5. 核心命令]]\n  - [[#5.1启动进程|5.1 启动进程]]\n  - [[#5.2停止与重启|5.2 停止与重启]]\n  - [[#5.3查看状态|5.3 查看状态]]\n  - [[#5.4删除进程|5.4 删除进程]]\n- [[#6.配置文件ecosystem.config.js|6. 配置文件 ecosystem.config.js]]\n  - [[#6.1基础配置|6.1 基础配置]]\n  - [[#6.2完整配置项说明|6.2 完整配置项说明]]\n  - [[#6.3多应用配置|6.3 多应用配置]]\n- [[#7.日志管理|7. 日志管理]]\n  - [[#7.1查看实时日志|7.1 查看实时日志]]\n  - [[#7.2日志切割|7.2 日志切割]]\n  - [[#7.3清空日志|7.3 清空日志]]\n- [[#8.进程监控与守护|8. 进程监控与守护]]\n  - [[#8.1进程守护机制|8.1 进程守护机制]]\n  - [[#8.2延迟启动|8.2 延迟启动]]\n  - [[#8.3最小运行时间|8.3 最小运行时间]]\n- [[#9.集群模式|9. 集群模式]]\n  - [[#9.1为什么使用集群模式|9.1 为什么使用集群模式]]\n  - [[#9.2启动集群|9.2 启动集群]]\n  - [[#9.3动态扩缩容|9.3 动态扩缩容]]\n- [[#10.开机自启|10. 开机自启]]\n  - [[#10.1Linux(systemd)|10.1 Linux (systemd)]])\n  - [[#10.2macOS(launchd)|10.2 macOS (launchd)]])\n  - [[#10.3Windows|10.3 Windows]]\n  - [[#10.4持久化进程列表|10.4 持久化进程列表]]\n- [[#11.环境变量管理|11. 环境变量管理]]\n- [[#12.热重载(Hot_Reload)|12. 热重载 (Hot Reload)]])\n- [[#13.应用部署|13. 应用部署]]\n  - [[#13.1简单部署|13.1 简单部署]]\n  - [[#13.2基于Git的部署|13.2 基于 Git 的部署]]\n  - [[#13.3部署钩子|13.3 部署钩子]]\n- [[#14.PM2Dashboard(Web监控)|14. PM2 Dashboard (Web 监控)]])\n- [[#15.常见问题排查|15. 常见问题排查]]\n  - [[#15.1进程不停重启|15.1 进程不停重启]]\n  - [[#15.2端口被占用|15.2 端口被占用]]\n  - [[#15.3内存占用过高|15.3 内存占用过高]]\n  - [[#15.4找不到pm2命令|15.4 找不到 pm2 命令]]\n  - [[#15.5开机自启不生效|15.5 开机自启不生效]]\n- [[#16.最佳实践|16. 最佳实践]]\n- [[#17.PM2vs其他进程管理器|17. PM2 vs 其他进程管理器]]\n\n---\n\n## 1.PM2简介\n\n**PM2** (Process Manager 2) 是一个现代化的 Node.js 进程管理器，内置负载均衡器。它可以帮助你：\n\n- 保持应用持续运行（守护进程）\n- 自动重启崩溃的应用\n- 轻松管理应用日志\n- 监控应用性能（CPU \u002F 内存）\n- 集群模式充分利用多核 CPU\n- 一键部署和开机自启\n\n> 📌 PM2 不仅可以管理 Node.js 应用，还支持 Python、Ruby、Java、Go 等多种语言的脚本。\n\n---\n\n## 2.环境要求\n\n| 组件 | 最低版本 | 推荐版本 |\n|------|---------|---------|\n| Node.js | v10.x | v16+ \u002F v18+ \u002F v20 LTS |\n| npm | 6.x | 最新版 |\n| 操作系统 | Linux kernel 3.18+ | Ubuntu 20.04+ \u002F CentOS 8+ \u002F macOS 10.14+ |\n\n检查当前环境：\n\n```bash\nnode -v\nnpm -v\nuname -a\n```\n\n---\n\n## 3.安装\n\n### 3.1Linux\u002FmacOS\n\n```bash\n# 全局安装\nnpm install pm2 -g\n\n# 或使用 yarn\nyarn global add pm2\n\n# 确认安装成功\npm2 -v\n# 输出类似：5.3.0\n```\n\n如果 `pm2` 命令不可用，检查 npm 全局 bin 目录是否在 PATH 中：\n\n```bash\n# 查找 pm2 安装位置\nwhich pm2\n# 或\nnpm bin -g\n\n# 查看 npm 全局前缀\nnpm config get prefix\n```\n\n如果仍有问题，可以直接使用 npx：\n\n```bash\nnpx pm2 -v\n```\n\n### 3.2Windows\n\n```powershell\n# 需要以管理员身份运行 PowerShell\nnpm install pm2 -g\n\n# Windows 推荐使用 pm2-windows-startup 实现开机自启\nnpm install pm2-windows-startup -g\npm2-startup install\n```\n\n### 3.3Docker中使用\n\n在 Docker 中运行 PM2 时，不建议使用 `pm2 startup`，而是直接在 Dockerfile 中使用 PM2 作为 PID 1：\n\n```dockerfile\n# Dockerfile 示例\nFROM node:18-alpine\n\nWORKDIR \u002Fapp\n\nCOPY package*.json .\u002F\nRUN npm install\n\nCOPY . .\n\n# 全局安装 pm2\nRUN npm install pm2 -g\n\n# 暴露端口\nEXPOSE 3000\n\n# 使用 pm2-runtime 替代 pm2 start，让 PM2 成为容器内 PID 1\nCMD [\"pm2-runtime\", \"start\", \"ecosystem.config.js\"]\n```\n\n---\n\n## 4.快速上手\n\n假设你有一个 `app.js` 文件：\n\n```javascript\n\u002F\u002F app.js\nconst http = require('http');\nconst server = http.createServer((req, res) => {\n  res.end('Hello PM2!');\n});\nserver.listen(3000);\nconsole.log('Server running at http:\u002F\u002Flocalhost:3000');\n```\n\n使用 PM2 启动：\n\n```bash\n# 启动应用\npm2 start app.js\n\n# 查看运行状态\npm2 list\n\n# 实时查看日志\npm2 logs\n\n# 监控面板\npm2 monit\n\n# 让进程在机器重启后也自动运行\npm2 save\npm2 startup\n```\n\n就这么简单！你的应用已经被 PM2 托管了。\n\n---\n\n## 5.核心命令\n\n### 5.1启动进程\n\n```bash\n# 基础启动\npm2 start app.js\n\n# 指定应用名称（推荐，方便后续管理）\npm2 start app.js --name my-app\n\n# 指定解释器（比如用 ts-node 运行 TypeScript）\npm2 start app.ts --interpreter ts-node\n\n# 运行非 Node.js 脚本\npm2 start script.py --interpreter python3\npm2 start server.rb --interpreter ruby\n\n# 运行 shell 命令\npm2 start \"echo hello && sleep 10\" --name my-script\n\n# 使用 npm 脚本\npm2 start npm --name my-app -- run start\n\n# 启动集群模式（4 个实例）\npm2 start app.js -i 4\npm2 start app.js --instances max  # 自动使用所有 CPU 核心\n\n# 延迟启动（等待 5 秒后再启动，多用于依赖启动）\npm2 start app.js --delay 5000\n```\n\n### 5.2停止与重启\n\n```bash\n# 停止\npm2 stop my-app          # 按名称\npm2 stop 0               # 按 ID\npm2 stop all             # 停止所有\n\n# 重启（先停止再启动）\npm2 restart my-app\npm2 restart 0\npm2 restart all\n\n# 重载（0 停机重启，仅对 Node.js 应用有效）\npm2 reload my-app\npm2 reload all\n\n# 场景说明：\n# - restart: 硬重启，进程先退出再启动，有短暂中断\n# - reload: 热重载，利用 cluster fork，保证 0 停机\n```\n\n### 5.3查看状态\n\n```bash\n# 进程列表（最常用）\npm2 list\n# 或\npm2 ls\npm2 status\n\n# 输出示例：\n# ┌────┬─────────────┬─────────┬─────────┬──────┬─────────┬──────┐\n# │ id │ name        │ mode    │ status  │ cpu  │ memory  │  ... │\n# ├────┼─────────────┼─────────┼─────────┼──────┼─────────┼──────┤\n# │ 0  │ my-app      │ cluster │ online  │ 0.5% │ 80.0mb  │  ... │\n# └────┴─────────────┴─────────┴─────────┴──────┴─────────┴──────┘\n\n# 查看某个应用的详细信息\npm2 show my-app\npm2 describe 0\n\n# 查看实时监控面板（交互式）\npm2 monit\n\n# 资源使用概览\npm2 prettylist\n```\n\n### 5.4删除进程\n\n```bash\n# 从 PM2 管理中删除（不会停止已运行的进程——但通常会先停止）\npm2 delete my-app\npm2 delete 0\npm2 delete all\n\n# 注意：pm2 delete 会同时停止进程。\n# 如果只想暂时停止，用 pm2 stop。\n```\n\n---\n\n## 6.配置文件ecosystem.config.js\n\n配置文件是管理多应用和复杂配置的最佳方式。PM2 约定使用 `ecosystem.config.js`。\n\n### 6.1基础配置\n\n```javascript\n\u002F\u002F ecosystem.config.js\nmodule.exports = {\n  apps: [\n    {\n      name: 'my-app',           \u002F\u002F 应用名称\n      script: '.\u002Fapp.js',       \u002F\u002F 入口脚本\n      cwd: '.\u002F',                \u002F\u002F 工作目录\n      instances: 1,             \u002F\u002F 实例数，'max' 表示所有核心\n      exec_mode: 'fork',        \u002F\u002F 'fork' 或 'cluster'\n      autorestart: true,        \u002F\u002F 崩溃自动重启\n      watch: false,             \u002F\u002F 是否监听文件变化重启\n      max_memory_restart: '1G', \u002F\u002F 内存超过此值重启\n      env: {\n        NODE_ENV: 'development',\n        PORT: 3000\n      },\n      env_production: {\n        NODE_ENV: 'production',\n        PORT: 80\n      }\n    }\n  ]\n};\n```\n\n使用配置文件：\n\n```bash\n# 启动\npm2 start ecosystem.config.js\n\n# 使用特定环境变量启动\npm2 start ecosystem.config.js --env production\n\n# 停止 \u002F 重启 \u002F 重载\npm2 stop ecosystem.config.js\npm2 restart ecosystem.config.js\npm2 reload ecosystem.config.js\n\n# 删除\npm2 delete ecosystem.config.js\n```\n\n### 6.2完整配置项说明\n\n```javascript\nmodule.exports = {\n  apps: [{\n    \u002F\u002F === 基本配置 ===\n    name: 'my-app',                    \u002F\u002F 应用名称\n    script: '.\u002Fapp.js',                \u002F\u002F 入口脚本路径\n    args: '--port 3000',               \u002F\u002F 传递给脚本的参数\n    cwd: '\u002Fvar\u002Fwww\u002Fmy-app',            \u002F\u002F 工作目录\n    interpreter: 'node',               \u002F\u002F 解释器路径（node\u002Fpython3\u002Fruby 等）\n    interpreter_args: '--harmony',     \u002F\u002F 解释器参数\n    \n    \u002F\u002F === 启动模式 ===\n    exec_mode: 'fork',                 \u002F\u002F 'fork'（单进程）| 'cluster'（集群）\n    instances: 1,                      \u002F\u002F 实例数量，'max' 表示 CPU 核心数\n    \n    \u002F\u002F === 进程守护 ===\n    autorestart: true,                 \u002F\u002F 异常退出自动重启\n    watch: false,                      \u002F\u002F 监听文件变化自动重启\n    watch_delay: 1000,                 \u002F\u002F 重启延迟（毫秒）\n    ignore_watch: ['node_modules', 'logs', '*.log'], \u002F\u002F 忽略监听的目录\n    max_memory_restart: '1G',          \u002F\u002F 内存超限自动重启\n    min_uptime: '10s',                 \u002F\u002F 最小运行时间（低于此算启动失败）\n    max_restarts: 10,                  \u002F\u002F 连续异常重启的最大次数\n    restart_delay: 4000,               \u002F\u002F 崩溃后重启前等待毫秒数\n    \n    \u002F\u002F === 日志配置 ===\n    error_file: '.\u002Flogs\u002Ferror.log',    \u002F\u002F 错误日志路径\n    out_file: '.\u002Flogs\u002Fout.log',        \u002F\u002F 标准输出日志路径\n    log_date_format: 'YYYY-MM-DD HH:mm:ss Z', \u002F\u002F 日志时间格式\n    merge_logs: false,                 \u002F\u002F 集群模式下合并所有实例日志\n    \n    \u002F\u002F === 环境变量 ===\n    env: {\n      NODE_ENV: 'development',\n      PORT: 3000,\n      DB_HOST: 'localhost'\n    },\n    env_production: {\n      NODE_ENV: 'production',\n      PORT: 80,\n      DB_HOST: '10.0.0.1'\n    },\n    env_test: {\n      NODE_ENV: 'test',\n      PORT: 3001\n    },\n    \n    \u002F\u002F === 钩子 ===\n    listen_timeout: 8000,              \u002F\u002F 发送 ready 信号的等待时间\n    kill_timeout: 5000,                \u002F\u002F 强制 kill 前的等待时间\n    wait_ready: false,                 \u002F\u002F 等待应用发送 ready 信号\n    \n    \u002F\u002F === 其他 ===\n    user: 'deploy',                    \u002F\u002F 以哪个用户运行（需要 root）\n    group: 'deploy',\n    force: false,                      \u002F\u002F 覆盖已存在的同名应用\n    update_env: false,                 \u002F\u002F 重启时是否更新环境变量\n    node_args: '--max-old-space-size=4096', \u002F\u002F 传递给 node 的参数\n  }]\n};\n```\n\n### 6.3多应用配置\n\n```javascript\n\u002F\u002F ecosystem.config.js - 一个配置管理多个应用\nmodule.exports = {\n  apps: [\n    {\n      name: 'web-api',\n      script: '.\u002Fapi\u002Fserver.js',\n      instances: 2,\n      exec_mode: 'cluster',\n      env: { NODE_ENV: 'production', PORT: 3000 }\n    },\n    {\n      name: 'worker',\n      script: '.\u002Fworkers\u002Ftask-runner.js',\n      instances: 1,\n      exec_mode: 'fork',\n      autorestart: true,\n      env: { NODE_ENV: 'production' }\n    },\n    {\n      name: 'cron-job',\n      script: '.\u002Fscripts\u002Fdaily-sync.js',\n      instances: 1,\n      exec_mode: 'fork',\n      \u002F\u002F 这是一个定时任务，跑完就退出，不需要守护\n      autorestart: false\n    }\n  ]\n};\n```\n\n---\n\n## 7.日志管理\n\n### 7.1查看实时日志\n\n```bash\n# 查看所有应用日志\npm2 logs\n\n# 查看指定应用日志\npm2 logs my-app\n\n# 只看错误日志\npm2 logs my-app --err\n\n# 只看标准输出\npm2 logs my-app --out\n\n# 限制最近 N 行\npm2 logs my-app --lines 100\n\n# 使用 grep 过滤\npm2 logs my-app | grep \"ERROR\"\n\n# 退出查看：Ctrl + C\n```\n\n### 7.2日志切割\n\nPM2 内置了 `pm2-logrotate` 模块用于日志轮转，防止日志文件无限增长。\n\n```bash\n# 安装\npm2 install pm2-logrotate\n\n# 配置\npm2 set pm2-logrotate:max_size 10M       # 单个日志文件最大 10M\npm2 set pm2-logrotate:retain 7           # 保留 7 份历史日志\npm2 set pm2-logrotate:compress true      # 压缩旧日志（gzip）\npm2 set pm2-logrotate:dateFormat YYYY-MM-DD_HH-mm-ss\npm2 set pm2-logrotate:workerInterval 30  # 每 30 秒检查一次\npm2 set pm2-logrotate:rotateModule true  # 启用切割模块\n\n# 查看当前配置\npm2 conf pm2-logrotate\n```\n\n### 7.3清空日志\n\n```bash\n# 清空所有日志\npm2 flush\n\n# 清空指定应用日志\npm2 flush my-app\n\n# 也可以直接删除日志文件\nrm -f ~\u002F.pm2\u002Flogs\u002F*.log\n```\n\n> ⚠️ 注意：`pm2 flush` 清空后需要重启进程才能生效（或等下次写入）。\n\n---\n\n## 8.进程监控与守护\n\n### 8.1进程守护机制\n\nPM2 的守护能力体现在以下场景：\n\n| 场景 | PM2 行为 |\n|------|---------|\n| 应用异常崩溃 | 自动重启 |\n| 应用 OOM（内存超限） | 触发 GC 或重启 |\n| 应用长时间无响应 | 可配合 `--wait-ready` + 健康检查 |\n| 操作系统重启 | 配合 `pm2 startup` + `pm2 save` 自动恢复 |\n\n关键配置：\n\n```javascript\n{\n  autorestart: true,        \u002F\u002F 默认 true\n  max_restarts: 10,        \u002F\u002F 10 分钟内最多重启 10 次，超过则停止\n  min_uptime: '10s',       \u002F\u002F 运行不足 10s 就算启动失败\n  restart_delay: 4000,     \u002F\u002F 重启前等 4 秒（避免死循环快速重启）\n  max_memory_restart: '1G' \u002F\u002F 内存超限自动重启\n}\n```\n\n### 8.2延迟启动\n\n当你的应用依赖其他服务（数据库、Redis、其他微服务）时，可以设置延迟启动：\n\n```javascript\n{\n  name: 'api',\n  script: '.\u002Fserver.js',\n  wait_ready: true,        \u002F\u002F 等应用发出就绪信号\n  listen_timeout: 10000   \u002F\u002F 最多等 10 秒\n}\n```\n\n然后在你的 Node.js 应用中发送就绪信号：\n\n```javascript\n\u002F\u002F server.js\nconst http = require('http');\nconst server = http.createServer(handler);\n\nserver.listen(3000, () => {\n  \u002F\u002F 告诉 PM2 应用已就绪\n  process.send && process.send('ready');\n  console.log('Server is ready on port 3000');\n});\n```\n\n### 8.3最小运行时间\n\n如果一个进程启动后很快就崩溃了，PM2 不会无限重启。它会统计一个\"指数退避\"策略：\n\n- 默认 `min_uptime: 1000ms`（1 秒）\n- 默认 `max_restarts: 15`（15 分钟内最多 15 次重启）\n- 超过限制后进程会被标记为 `errored` 状态并停止重启\n\n```bash\n# 查看进程重启次数\npm2 show my-app | grep restart\n```\n\n---\n\n## 9.集群模式\n\n### 9.1为什么使用集群模式\n\nNode.js 默认单线程运行，利用集群模式可以：\n\n- ✅ **充分利用多核 CPU** —— 每个核心运行一个进程\n- ✅ **零停机重启** —— reload 时逐个替换实例\n- ✅ **内置负载均衡** —— PM2 自动分发请求到各实例\n\n### 9.2启动集群\n\n```bash\n# 方式一：命令行直接启动\npm2 start app.js -i max          # 用所有 CPU 核心\npm2 start app.js -i 4            # 用 4 个实例\npm2 start app.js -i 2 --name api # 2 实例并命名\n\n# 方式二：配置文件\nmodule.exports = {\n  apps: [{\n    name: 'api',\n    script: '.\u002Fapp.js',\n    exec_mode: 'cluster',\n    instances: 'max'    \u002F\u002F 或数字 2, 4 等\n  }]\n};\n```\n\n### 9.3动态扩缩容\n\n```bash\n# 增加实例（热增加）\npm2 scale api +2      # 当前基础上 +2\npm2 scale api 6       # 精确到 6 个实例\n\n# 减少实例\npm2 scale api -2\n\n# 查看集群分布\npm2 list\n```\n\n> 💡 **实践建议**：`instances: 'max'` 在小型机器上方便，但生产环境建议设为 CPU 核心数减 1，留一个核心给系统和其他服务。\n\n---\n\n## 10.开机自启\n\n### 10.1Linux(systemd)\n\n```bash\n# 生成并安装 systemd 服务\npm2 startup\n# 输出类似：[PM2] Init System found: systemd\n# 按提示复制并执行一条 sudo 命令\n\n# 示例输出（你的实际命令可能不同）：\n# [PM2] You have to run this command as root:\n# sudo env PATH=$PATH:\u002Fusr\u002Fbin \u002Fusr\u002Flib\u002Fnode_modules\u002Fpm2\u002Fbin\u002Fpm2 startup systemd -u $USER --hp $HOME\n\n# 执行提示的命令\nsudo env PATH=$PATH:\u002Fusr\u002Fbin \u002Fusr\u002Flib\u002Fnode_modules\u002Fpm2\u002Fbin\u002Fpm2 startup systemd -u $USER --hp $HOME\n\n# 保存当前进程列表（关键！）\npm2 save\n\n# 查看 systemd 服务状态\nsudo systemctl status pm2-$USER\n\n# 重启机器测试\nsudo reboot\n```\n\n### 10.2macOS(launchd)\n\n```bash\n# 生成 launchd 配置\npm2 startup\n# 按提示执行 sudo 命令\n\n# 保存进程列表\npm2 save\n```\n\n### 10.3Windows\n\n```powershell\n# Windows 上推荐使用 pm2-windows-startup\nnpm install -g pm2-windows-startup\npm2-startup install\n\n# 保存进程列表\npm2 save\n\n# 或使用 nssm（更专业的方案）\n# 下载 nssm: https:\u002F\u002Fnssm.cc\u002Fdownload\nnssm install PM2 \"C:\\Users\\\u003Cyou>\\AppData\\Roaming\\npm\\pm2.cmd\" \"pm2 resurrect\"\nnssm set PM2 AppDirectory \"C:\\path\\to\\project\"\nnssm set PM2 Start SERVICE_AUTO_START\nnssm start PM2\n```\n\n### 10.4持久化进程列表\n\n```bash\n# 保存当前所有进程到 ~\u002F.pm2\u002Fdump.pm2\npm2 save\n\n# 从保存的列表恢复（通常开机自启自动调用）\npm2 resurrect\n\n# 查看已保存的列表\ncat ~\u002F.pm2\u002Fdump.pm2\n```\n\n> ⚠️ **重要提醒**：每次修改进程列表（start\u002Fstop\u002Fdelete）后都应该执行 `pm2 save`，否则重启后不会恢复最新状态！\n\n---\n\n## 11.环境变量管理\n\n```bash\n# 方式一：启动时通过 --env 指定\npm2 start ecosystem.config.js --env production\n\n# 方式二：命令行直接传\nNODE_ENV=production PORT=8080 pm2 start app.js\n\n# 方式三：配置文件中定义多环境\n# ecosystem.config.js\nmodule.exports = {\n  apps: [{\n    name: 'api',\n    script: '.\u002Fapp.js',\n    env:            { NODE_ENV: 'development', PORT: 3000 },\n    env_staging:    { NODE_ENV: 'staging',    PORT: 3000 },\n    env_production: { NODE_ENV: 'production', PORT: 80 }\n  }]\n};\n\n# 切换环境\npm2 start ecosystem.config.js --env staging\n\n# 更新已运行进程的环境变量并重启\npm2 restart api --update-env\n```\n\n---\n\n## 12.热重载(Hot_Reload)\n\n### 文件监听自动重启\n\n```bash\n# 命令行方式\npm2 start app.js --watch\n\n# 配置文件方式\nmodule.exports = {\n  apps: [{\n    name: 'api',\n    script: '.\u002Fapp.js',\n    watch: true,\n    watch_delay: 1000,\n    ignore_watch: ['node_modules', 'logs', '*.log', 'public']\n  }]\n};\n```\n\n### 集群零停机重载\n\n```bash\n# reload 会逐个替换集群实例，实现零停机\npm2 reload api\n\n# 也可以配合配置文件\npm2 reload ecosystem.config.js\n```\n\n> 🆚 **reload vs restart**：`restart` 硬重启所有进程，有短暂中断；`reload` 利用集群特性逐台替换，适合生产环境滚动发布。\n\n---\n\n## 13.应用部署\n\n### 13.1简单部署\n\n```bash\n# 在本地打包上传后，服务器上执行\ncd \u002Fvar\u002Fwww\u002Fmy-app\nnpm install\npm2 restart my-app --update-env\n```\n\n### 13.2基于Git的部署\n\nPM2 内置简单的部署功能：\n\n```javascript\n\u002F\u002F ecosystem.config.js\nmodule.exports = {\n  apps: [{\n    name: 'api',\n    script: '.\u002Fapp.js'\n  }],\n  deploy: {\n    production: {\n      user: 'deploy',\n      host: '192.168.1.100',\n      port: 22,\n      ref: 'origin\u002Fmain',\n      repo: 'git@github.com:my-org\u002Fmy-app.git',\n      path: '\u002Fvar\u002Fwww\u002Fmy-app',\n      ssh_options: 'StrictHostKeyChecking=no',\n      'post-deploy': 'npm install && pm2 startOrRestart ecosystem.config.js --env production'\n    }\n  }\n};\n```\n\n```bash\n# 首次部署（在本地执行）\npm2 deploy ecosystem.config.js production setup\n\n# 后续部署\npm2 deploy ecosystem.config.js production update\n\n# 回滚\npm2 deploy ecosystem.config.js production revert 1\n\n# 查看部署状态\npm2 deploy ecosystem.config.js production status\n```\n\n### 13.3部署钩子\n\n```javascript\n\u002F\u002F ecosystem.config.js 中配置部署生命周期钩子\ndeploy: {\n  production: {\n    \u002F\u002F ...\n    'pre-deploy': 'echo \"开始部署\"',\n    'post-deploy': 'npm install && npm run build && pm2 reload ecosystem.config.js --env production',\n    'post-setup': 'echo \"首次部署完成\"'\n  }\n}\n```\n\n---\n\n## 14.PM2Dashboard(Web监控)\n\nPM2 提供免费的 Web 监控面板 `pm2.io`：\n\n```bash\n# 注册账号（首次使用）\npm2 register\n\n# 或者直接登录\npm2 login\n\n# 启动监控\npm2 monitor\n# 会输出一个 Dashboard URL，类似：\n# https:\u002F\u002Fapp.pm2.io\u002F...\n```\n\n通过 Dashboard 你可以：\n\n- 📊 实时查看所有服务器的进程状态\n- 📈 CPU \u002F 内存 \u002F 网络流量图表\n- 📝 在线查看和搜索日志\n- ⚡ 远程重启 \u002F 重载进程\n- 🔔 设置告警规则（内存过高、崩溃等）\n- 🗂️ 管理多台服务器\n\n也可以试试开源替代：\n- **PM2 Plus** —— PM2 官方企业版\n- **Keymetrics** —— SaaS 监控服务\n- **自定义监控** —— 结合 Prometheus + Grafana\n\n---\n\n## 15.常见问题排查\n\n### 15.1进程不停重启\n\n**症状**：`pm2 list` 显示 `status: errored` 或重启计数不断增加。\n\n**排查步骤**：\n\n```bash\n# 1. 看日志找报错原因\npm2 logs my-app --lines 50 --nostream\n\n# 2. 查看详细信息\npm2 show my-app\n\n# 3. 手动运行看报什么错\nnode app.js\n\n# 4. 常见原因\n#    - 端口被占用 → 改端口或 kill 占用进程\n#    - 依赖未安装 → npm install\n#    - 环境变量缺失 → pm2 env 0 检查\n#    - 代码异常 → 修 bug\n```\n\n### 15.2端口被占用\n\n```bash\n# 查找占用 3000 端口的进程\nsudo lsof -i :3000\n# 或\nsudo netstat -tlnp | grep 3000\n\n# 杀掉占用进程\nsudo kill -9 $(sudo lsof -t -i:3000)\n\n# 或使用 pm2 的 reload（集群模式下自动处理）\npm2 reload my-app\n```\n\n### 15.3内存占用过高\n\n```bash\n# 临时排查\npm2 monit            # 看实时内存\npm2 logs --lines 100 # 看是否有报错导致泄漏\n\n# 限制内存，超限自动重启\n# ecosystem.config.js 中：\n{\n  max_memory_restart: '500M'  # 或 '1G', '512M'\n}\n\n# 使用 v8-profiler \u002F clinic.js 分析内存泄漏\n# 或使用 --inspect 参数配合 Chrome DevTools\nnode --inspect app.js\n```\n\n### 15.4找不到pm2命令\n\n```bash\n# 原因：npm 全局 bin 不在 PATH 中\n\n# 方案 1：重新安装到默认位置\nnpm install -g pm2\n\n# 方案 2：查看并添加 PATH\nnpm config get prefix\n# 假设输出 \u002Fusr\u002Flocal，则添加：\nexport PATH=\"\u002Fusr\u002Flocal\u002Fbin:$PATH\"\n# 写入 ~\u002F.bashrc 或 ~\u002F.zshrc 持久化\n\n# 方案 3：用 npx 代替\nnpx pm2 list\n```\n\n### 15.5开机自启不生效\n\n```bash\n# 排查步骤：\n\n# 1. 确认 startup 脚本已生成\nls -la ~\u002F.pm2\u002Fdump.pm2    # 应该存在\nsystemctl status pm2-$USER\n\n# 2. 确认进程列表已保存\npm2 save                  # 每次 start\u002Fstop\u002Fdelete 后都要 save\n\n# 3. 手动测试 resurrect\npm2 resurrect             # 应该能恢复所有进程\n\n# 4. 如果还是不行，重新生成 startup\npm2 startup               # 按提示重新执行 sudo 命令\npm2 save\n\n# 5. Docker \u002F 容器内\n#    容器内不要用 pm2 startup，直接在 Dockerfile 用 pm2-runtime\n```\n\n---\n\n## 16.最佳实践\n\n### ✅ 推荐做法\n\n| 实践 | 原因 |\n|------|------|\n| 使用 `ecosystem.config.js` | 配置版本化管理，团队共享方便 |\n| 始终给应用命名 `--name` | `my-app` 比 `0` 好记 |\n| 生产环境用 `--env production` | 明确区分环境 |\n| `instances: max`（集群模式） | 充分利用多核 |\n| `max_memory_restart` | 防止内存泄漏拖垮机器 |\n| `pm2 save` + `pm2 startup` | 保证重启自动恢复 |\n| `pm2 reload` 替代 `pm2 restart` | 零停机发布 |\n| 安装 `pm2-logrotate` | 防止日志撑爆磁盘 |\n| 配合反向代理 (nginx) | 做 SSL 终止、负载均衡 |\n\n### ❌ 避免做法\n\n| 反模式 | 正确做法 |\n|--------|---------|\n| 用 PM2 管理一次性脚本（跑完就退出） | 加 `autorestart: false` 或用 systemd cron |\n| 所有配置硬编码在命令行 | 放到 ecosystem.config.js |\n| 忘记 `pm2 save` 就重启机器 | 养成习惯：改完进程列表就 save |\n| Docker 容器里用 `pm2 startup` | 用 `pm2-runtime` 作为 CMD |\n| 生产环境不设 `max_restarts` | 防止无限重启循环耗尽资源 |\n\n---\n\n## 17.PM2vs其他进程管理器\n\n| 特性 | PM2 | Forever | systemd | Supervisor | Docker |\n|------|-----|---------|---------|-----------|--------|\n| 语言 | Node.js | Node.js | C | Python | Go |\n| 守护 Node.js | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ |\n| 集群模式 | ✅ 内置 | ❌ | ✅ (需配置) | ❌ | ✅ |\n| 日志管理 | ✅ 内置 | ✅ 基础 | ❌ journalctl | ✅ 基础 | 需要额外配置 |\n| 监控面板 | ✅ pm2.io | ❌ | ❌ | ❌ | 需要 Prometheus |\n| 跨平台 | ✅ | ✅ | Linux | Linux\u002FMac | 全平台 |\n| 多语言支持 | ✅ | ❌ | ✅ | ✅ | ✅ |\n| 零停机重载 | ✅ reload | ❌ | 需额外配置 | ❌ | ✅ |\n| 学习成本 | 低 | 低 | 中 | 中 | 高 |\n| 适用场景 | Node.js 应用首选 | 简单场景 | 系统级服务 | 多语言服务 | 容器化部署 |\n\n### 选型建议\n\n- **纯 Node.js 项目** → **PM2**（首选，功能最匹配）\n- **系统级服务 \u002F 非 Node.js** → **systemd**（Linux 原生）或 **Supervisor**\n- **微服务 \u002F 容器化架构** → **Docker + Kubernetes**\n\n---\n\n## 附录：速查命令表\n\n```bash\n# === 启动 ===\npm2 start app.js                          # 启动\npm2 start app.js --name api               # 命名启动\npm2 start app.js -i 4                     # 集群 4 实例\npm2 start app.js -i max                   # 集群满核\npm2 start npm --name api -- run start     # 用 npm 脚本\npm2 start ecosystem.config.js             # 用配置文件\n\n# === 管理 ===\npm2 list                                  # 查看列表\npm2 show api                              # 查看详情\npm2 logs                                  # 查看日志\npm2 monit                                 # 交互式监控\n\npm2 stop api                              # 停止\npm2 restart api                           # 硬重启\npm2 reload api                            # 热重载（0 停机）\npm2 delete api                            # 删除\n\npm2 scale api +2                          # 扩缩容\npm2 flush                                 # 清空日志\n\n# === 持久化 ===\npm2 save                                  # 保存进程列表\npm2 resurrect                             # 恢复进程列表\npm2 startup                               # 生成开机自启脚本\n\n# === 配置 ===\npm2 env 0                                 # 查看进程环境变量\npm2 conf                                  # 查看 pm2 全局配置\npm2 describe api                          # 同 show\n\n# === 部署 ===\npm2 deploy ecosystem.config.js production update   # 部署\npm2 deploy ecosystem.config.js production revert 1 # 回滚\n```\n\n---\n\n> 📖 **参考资料**\n> - 官方文档：https:\u002F\u002Fpm2.keymetrics.io\u002Fdocs\u002Fusage\u002Fpm2-doc-single-page\u002F\n> - GitHub：https:\u002F\u002Fgithub.com\u002FUnitech\u002Fpm2\n> - PM2 Logrotate：https:\u002F\u002Fgithub.com\u002Fkeymetrics\u002Fpm2-logrotate\n\n---\n\n*文档版本：v1.0 | 更新日期：2026-10-16*",29,false,"2026-10-19T19:26:40",{"list":93,"total":10,"page":20,"size":94},[],30]