跳到主要内容
注册无需实名认证
安云主机 AnYun VPS

教程 · 应用与数据库

用 pm2 让 Node.js 应用常驻并开机自启

难度

进阶

预计时长

25 分钟

步骤

7

最近修订

基准系统

Debian 12

要点

用 pm2 让 Node.js 应用常驻并开机自启

pm2 负责进程守护、崩溃重启与日志管理。让应用在重启后仍然自动回来需要三步:pm2 start 启动、pm2 save 保存进程列表、pm2 startup 生成 systemd 单元 —— 三步缺一不可,只做前两步的服务器重启后应用不会自己起来。

前置条件

开始之前,先确认这些都具备

  • 一个可以本地跑起来的 Node.js 项目
  • 已创建非 root 部署用户(应用应当以它的身份运行)

操作步骤

7

  1. 步骤 01 / 07

    安装 Node.js #

    发行版仓库里的 Node 往往落后好几个大版本。生产环境用 NodeSource 的源装 LTS 版本;如果需要在同一台机器上切换多个 Node 版本,用 nvm 更灵活,但 nvm 装的 Node 属于某个用户,配 systemd 自启时路径要写全。

    Shell
    curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
    sudo apt install -y nodejs
    
    node -v
    npm -v
  2. 步骤 02 / 07

    安装 pm2 #

    pm2 全局安装一次即可。用部署用户安装还是 root 安装都能用,但要固定下来 —— 两个用户各装一份 pm2、各有一份进程列表,是排查「进程明明在跑却看不到」的常见原因。

    Shell
    sudo npm install -g pm2
    pm2 --version
  3. 步骤 03 / 07

    用 ecosystem 文件描述应用 #

    把启动参数写进配置文件,而不是记在某个人的终端历史里。instances 与 exec_mode 决定是否开多进程;max_memory_restart 是内存泄漏时的兜底 —— 与其被 OOM Killer 突然杀掉,不如让 pm2 优雅重启。

    JavaScript
    // ecosystem.config.cjs
    module.exports = {
      apps: [
        {
          name: 'api',
          script: './dist/server.js',
          cwd: '/home/deploy/apps/api',
          instances: 2,
          exec_mode: 'cluster',
          max_memory_restart: '400M',
          env: {
            NODE_ENV: 'production',
            PORT: 3000,
            HOST: '127.0.0.1',
          },
          error_file: '/home/deploy/logs/api-error.log',
          out_file: '/home/deploy/logs/api-out.log',
        },
      ],
    }
  4. 步骤 04 / 07

    启动并查看状态 #

    启动后先看日志确认没有启动即崩溃的情况。pm2 会不断重启崩溃的进程,如果配置有误,表现就是 restart 次数飞快上涨 —— 那个数字比「status: online」更能说明问题。

    Shell
    pm2 start ecosystem.config.cjs
    pm2 list
    pm2 logs api --lines 100
    pm2 describe api
  5. 步骤 05 / 07

    配置开机自启(最容易漏的一步) #

    pm2 startup 会生成并安装一个 systemd 单元;用 -u 与 --hp 指定以哪个用户、哪个家目录恢复进程。之后必须再执行一次 pm2 save,把当前进程列表写进快照 —— 开机时恢复的正是这份快照。

    Shell
    sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u deploy --hp /home/deploy
    
    # 切回 deploy 用户执行
    pm2 save
    
    # 真的重启一次来验证,别只相信命令没报错
    sudo reboot
    # 重连后:
    pm2 list
  6. 步骤 06 / 07

    开启日志轮转 #

    pm2 默认把日志一直往一个文件里追加,小磁盘上这是个定时炸弹。pm2-logrotate 模块按大小切分并保留有限份数。

    Shell
    pm2 install pm2-logrotate
    pm2 set pm2-logrotate:max_size 10M
    pm2 set pm2-logrotate:retain 7
    pm2 set pm2-logrotate:compress true
  7. 步骤 07 / 07

    更新部署时用 reload 而不是 restart #

    cluster 模式下 reload 会逐个替换工作进程,对外表现为零停机;restart 则是全部停掉再起来,中间那几秒访客会看到 502。

    Shell
    cd /home/deploy/apps/api
    git pull
    npm ci --omit=dev
    npm run build
    
    pm2 reload api
    pm2 logs api --lines 50

常见错误

这一步最容易踩的坑

下面每一条都对应一个真实会发生的故障。先读完再动手,比出问题之后再回来查要省时间。

  • 忘了 pm2 save。服务器重启后 pm2 起来了,进程列表却是空的 —— 这是「重启后网站没了」的头号原因。
  • 用 root 跑应用图省事。应用被攻破就等于整台机器被攻破,用部署用户运行只多花两分钟。
  • 应用监听 0.0.0.0。反向代理的所有防护都会被公网直连绕过,监听 127.0.0.1 才对。
  • cluster 模式配多实例,但应用把会话存在进程内存里,结果用户随机掉登录。多实例要求会话外置(Redis 或数据库)。
  • 日志不轮转,几个月后磁盘写满,服务器上什么都写不进去,故障表现却千奇百怪。
  • 在 1 GB 内存机器上跑 npm ci 或 npm run build 被 OOM 结束。加 swap,或者在本地构建好再上传产物。
  • 同时用 pm2 和 systemd 直接守护同一个应用,两边互相重启,端口反复被占。选一个。

这篇教程的边界

  • 命令以 Debian 12 为准。Ubuntu 与 Rocky Linux 的差异只在正文明确标注之处,未标注的部分请以你所用发行版的官方文档为准。
  • 示例中的 IP 来自文档保留段 203.0.113.0/24,域名为 example.com,端口为示意值。复制后必须替换成自己的值, 原样执行不会有任何效果。
  • 教程不能替代备份。任何会改动数据或线上流量的步骤,执行前先确认有一份验证过能恢复的备份。
  • 本站不提供任何用于绕过网络审查的配置或说明,这篇也不例外。

发现命令过时或有误,请发邮件到 [email protected]。 指出错误的邮件比沉默的旧文档有价值得多。

联系 工单
扫码
手机访问

扫码在手机上打开