pm2同时启动多个js文件,并且可以动态的增添进程

90 阅读1分钟

当有多个进程需要启动 ,并且可以随时的启动或停止其中的任意一个时,通过chokidar来监听变化,执行相应的操作

​编辑

1.创建config.js,包含启动的名称与路径

module.exports = {
  "apps": [
    {
      "name": "one",
      "script": "./1.js"
    },
 {
      "name": "two",
      "script": "./two.js"
    }
  ]
};

2.书写监听文件,watch.js

const chokidar = require('chokidar');
const { exec } = require('child_process');

// 启动 PM2 并加载 config.js
function startPM2() {
  exec('pm2 start config.js', (err, stdout, stderr) => {
    if (err) {
      console.error(`Error starting PM2: ${stderr}`);
      return;
    }
    console.log(`PM2 started successfully: ${stdout}`);
  });
}

// 重新启动 PM2 并执行 update.js
function restartPM2AndUpdate() {
  exec('node ./update.js', (err, stdout, stderr) => {
    if (err) {
      console.error(`Error running update.js: ${stderr}`);
      return;
    }
    console.log(`update.js executed successfully: ${stdout}`);
  });
}

// 监听 config.js 文件的变化
const watcher = chokidar.watch('config.js', {
  persistent: true,
  ignoreInitial: true, // 忽略初始的文件状态
});

// 当文件发生变化时,重新启动 PM2 并执行 update.js
watcher.on('change', (path) => {
  console.log(`File ${path} has changed. Restarting PM2 and updating processes...`);
  restartPM2AndUpdate();
});

// 初始启动 PM2
startPM2();

3.书写更新进程方法 updata.js


const { exec } = require('child_process');
// 读取 PM2 配置文件
const config = require('./config.js');

// 获取当前运行的应用列表
async function getCurrentProcesses() {
  return new Promise((resolve, reject) => {
    exec('pm2 jlist', (err, stdout) => {
      if (err) {
        console.error('Error fetching current PM2 processes:', err);
        reject(err);
      } else {
        resolve(JSON.parse(stdout).map(proc => proc.name));
      }
    });
  });
}

// 停止进程
async function stopProcess(procName) {
  return new Promise((resolve, reject) => {
    exec(`pm2 stop ${procName}`, (err, stdout) => {
      if (err) {
        console.error(`Error stopping process ${procName}:`, err);
        reject(err);
      } else {
        console.log(`Process ${procName} stopped successfully`);
        resolve();
      }
    });
  });
}

// 删除进程(从 PM2 中完全移除)
async function deleteProcess(procName) {
  return new Promise((resolve, reject) => {
    exec(`pm2 delete ${procName}`, (err, stdout) => {
      if (err) {
        console.error(`Error deleting process ${procName}:`, err);
        reject(err);
      } else {
        console.log(`Process ${procName} deleted successfully`);
        resolve();
      }
    });
  });
}

// 启动进程
async function startProcess(procName) {
  return new Promise((resolve, reject) => {
    exec(`pm2 start config.js --only ${procName}`, (err, stdout) => {
      if (err) {
        console.error(`Error starting process ${procName}:`, err);
        reject(err);
      } else {
        console.log(`Process ${procName} started successfully`);
        resolve();
      }
    });
  });
}

// 保存 PM2 配置
async function savePM2Config() {
  return new Promise((resolve, reject) => {
    exec('pm2 save', (err, stdout) => {
      if (err) {
        console.error('Error saving PM2 configuration:', err);
        reject(err);
      } else {
        console.log('PM2 configuration saved successfully');
        resolve();
      }
    });
  });
}

// 更新进程
async function updateProcesses() {
  try {
    const currentProcesses = await getCurrentProcesses();
    const newProcesses = config.map(app => app.name);
    const toDelete = currentProcesses.filter(proc => !newProcesses.includes(proc));
    const toStart = newProcesses.filter(proc => !currentProcesses.includes(proc));
    const toRestart = newProcesses.filter(proc => currentProcesses.includes(proc));
    for (const proc of toDelete) {
      await stopProcess(proc);
      await deleteProcess(proc);
    }
    for (const proc of toStart) {
      await startProcess(proc);
    }
    for (const proc of toRestart) {
      await exec(`pm2 restart ${proc}`, (err, stdout) => {
        if (err) {
          console.error(`Error restarting process ${proc}:`, err);
        } else {
          console.log(`Process ${proc} restarted successfully`);
        }
      });
    }
    await savePM2Config();
  } catch (error) {
    console.error('Error updating processes:', error);
  }
}

// 执行更新
updateProcesses();

使用node 启动 watch.js,可以通过增删改config.js。app中的内容,来动态变化启动那几个进程,会将已经启动但删除的进程停掉,同时启动新加入的进程