Introduction

According to Murphy’s law: “Anything that can go wrong will go wrong”. PM2 does a great job of restarting crashed processes automatically, but there are edge cases or misconfigurations where a process stays down without you noticing. So let’s build a simple cron job to periodically check if our PM2 processes are actually online or have crashed for whatever reason.

How it works

The script uses Node’s built-in execSync to run pm2 jlist, which returns the full JSON output of all PM2 processes. It then filters for processes with status === 'online' and compares the count against the expected number. If the count does not match, it fires an alert. You can hook up any notification channel you prefer (email, Slack, etc.).

The key things to customise before running it:

  • numOfProcessesShouldBeOnline: set this to the exact number of processes that must be online on your server (including pm2-logrotate if you have it installed)
  • sendEmail / sendSlack: replace with your actual notification logic

Code

// pm2check.ts
import 'dotenv/config';
import { execSync } from 'child_process';

interface Pm2Jlist {
  pid: number;
  name: string;
  pm2_env: {
    status: string;
  };
  // ...
}

async function main() {
  try {
    // Number of processes that should be online: app and pm2-logrotate
    const numOfProcessesShouldBeOnline = 2;
    const pm2ls = execSync('pm2 jlist'); // JSON output of pm2 list
    const pm2Json: Pm2Jlist[] = JSON.parse(pm2ls.toString());
    const onlineProcesses = pm2Json
      .map(p => ({ name: p.name, status: p.pm2_env.status }))
      .filter(p => p.status === 'online');
    if (onlineProcesses.length !== numOfProcessesShouldBeOnline) {
      const msg = `Online processes are ${onlineProcesses.length}, should be ${numOfProcessesShouldBeOnline}!`;
      console.error(msg);
      // Send your preferred alert: email, slack, whatever
      await sendEmail(msg);
      await sendSlack(msg);
    }
    process.exit();
  } catch (err) {
    console.error(err);
    process.exit(1);
  }
}

main();

Cron

Then you can execute this cron for example every 5 minutes:

*/5 * * * * node dist/server/crons/pm2check.js >> /home/ubuntu/myproject/logs/crons_pm2check.log 2>&1'

To edit your crontab, run crontab -e on the server and paste the line above, adjusting the path to your compiled JS file and your log directory.

The redirect >> ... 2>&1 appends both stdout and stderr to a log file so you can inspect past runs if something unexpected happens.

Conclusion

With less than 50 lines of code and a single cron entry you get a lightweight watchdog for your PM2 processes. It won’t replace a full monitoring solution, but it’s a practical safety net that takes minutes to set up and immediately alerts you when a process goes down and stays down.