当有多个进程需要启动 ,并且可以随时的启动或停止其中的任意一个时,通过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中的内容,来动态变化启动那几个进程,会将已经启动但删除的进程停掉,同时启动新加入的进程