refactor(updatenotification): replace pm2 usage with node logic (#4134)

We can rely on PM2's native restart-on-exit behavior instead of the
programmatic pm2 API.

Fixes
https://github.com/MagicMirrorOrg/MagicMirror/security/dependabot/82 by
removing pm2.

Note: Originally this PR was intended to update pm2, but after
discussion, we decided to replace it instead. See the discussion below.
This commit is contained in:
Kristjan ESPERANTO
2026-05-03 09:51:08 +02:00
committed by GitHub
parent 0905d66a91
commit f2759ad4f6
5 changed files with 112 additions and 1407 deletions
@@ -49,7 +49,6 @@ module.exports = NodeHelper.create({
case "CONFIG":
this.config = payload;
this.updateHelper = new UpdateHelper(this.config);
await this.updateHelper.check_PM2_Process();
break;
case "MODULES":
// if this is the 1st time thru the update check process
@@ -1,6 +1,5 @@
const Exec = require("node:child_process").exec;
const Spawn = require("node:child_process").spawn;
const fs = require("node:fs");
const Log = require("logger");
@@ -47,8 +46,6 @@ class Updater {
this.autoRestart = config.updateAutorestart;
this.moduleList = {};
this.updating = false;
this.usePM2 = false; // don't use pm2 by default
this.PM2Id = null; // pm2 process number
this.version = global.version;
this.root_path = global.root_path;
Log.info("Updater Class Loaded!");
@@ -122,7 +119,7 @@ class Updater {
Result.updated = true;
if (this.autoRestart) {
Log.info("Update done");
setTimeout(() => this.restart(), 3000);
setTimeout(() => this.nodeRestart(), 3000);
} else {
Log.info("Update done, don't forget to restart MagicMirror!");
Result.needRestart = true;
@@ -133,23 +130,6 @@ class Updater {
});
}
// restart rules (pm2 or node --run start)
restart () {
if (this.usePM2) this.pm2Restart();
else this.nodeRestart();
}
// restart MagicMirror with "pm2": use PM2Id for restart it
pm2Restart () {
Log.info("[PM2] restarting MagicMirror...");
const pm2 = require("pm2");
pm2.restart(this.PM2Id, (err) => {
if (err) {
Log.error("[PM2] restart Error", err);
}
});
}
// restart MagicMirror with "node --run start"
nodeRestart () {
Log.info("Restarting MagicMirror...");
@@ -160,58 +140,6 @@ class Updater {
process.exit();
}
// Check using pm2
check_PM2_Process () {
Log.info("Checking PM2 using...");
return new Promise((resolve) => {
if (fs.existsSync("/.dockerenv")) {
Log.info("[PM2] Running in docker container, not using PM2 ...");
resolve(false);
return;
}
if (process.env.unique_id === undefined) {
Log.info("[PM2] You are not using pm2");
resolve(false);
return;
}
Log.debug(`[PM2] Search for pm2 id: ${process.env.pm_id} -- name: ${process.env.name} -- unique_id: ${process.env.unique_id}`);
const pm2 = require("pm2");
pm2.connect((err) => {
if (err) {
Log.error("[PM2]", err);
resolve(false);
return;
}
pm2.list((err, list) => {
if (err) {
Log.error("[PM2] Can't get process List!");
resolve(false);
return;
}
list.forEach((pm) => {
Log.debug(`[PM2] found pm2 process id: ${pm.pm_id} -- name: ${pm.name} -- unique_id: ${pm.pm2_env.unique_id}`);
if (pm.pm2_env.status === "online" && process.env.name === pm.name && +process.env.pm_id === +pm.pm_id && process.env.unique_id === pm.pm2_env.unique_id) {
this.PM2Id = pm.pm_id;
this.usePM2 = true;
Log.info(`[PM2] You are using pm2 with id: ${this.PM2Id} (${pm.name})`);
resolve(true);
} else {
Log.debug(`[PM2] pm2 process id: ${pm.pm_id} don't match...`);
}
});
pm2.disconnect();
if (!this.usePM2) {
Log.info("[PM2] You are not using pm2");
resolve(false);
}
});
});
});
}
// check if module is MagicMirror
isMagicMirror (module) {
if (module === "MagicMirror") return true;