To run NodeJS scripts and apps constantly, we usually use pm2 (some prefer forever). However, some scripts require a brute force restart from time to time as they do not fare better in uninterrupted longer runs. Mostly, the reason is memory leaks of packages you are bound to use but have no control over. There could be other reasons too.
There must surely be other and more elegant ways to do this, but a simple node script that also shows you the log of all previous restarts is what I have used when I needed one.
For this you need to install cron module. Then paste and save the below script in a file, and run it either with pm2 or node.
const { exec } = require('child_process');
const CronJob = require('cron').CronJob;
const restartCommand = "pm2 restart 0";
const listCommand = "pm2 list";
console.log("Starting App Restarter");
const restartApp = function () {
exec(restartCommand, (err, stdout, stderr) => {
if (!err && !stderr) {
console.log(new Date(), `App restarted!!!`);
listApps();
}
else if (err || stderr) {
console.log(new Date(), `Error in executing ${restartCommand}`, err || stderr);
}
});
}
function listApps() {
exec(listCommand, (err, stdout, stderr) => {
// handle err if you like!
console.log(`pm2 list`);
console.log(`${stdout}`);
});
}
new CronJob('0 0 2 * * *', function() {
console.log('2 am Los_Angeles time, restarting the zombieApp');
restartApp();
}, null, true, 'America/Los_Angeles');
- We need
exec
fromchild_process
(child_process comes with node) CronJob
will run our given function at the given time- “pm2 restart 0” is our
restartCommand
. 0 is the id of the process. Change it with the id you have listCommand
is to list the pm2 processes after restart, just for our reference- With
new CronJob
we actually set up a cron job that is supposed to run at 2 am, Los Angeles time each day. It callsrestartApp()
restartApp
executes therestartCommand
, and on success callslistApps()
- Lastly,
listApps
executes thelistCommand
and we get to see the running processes after the restart
3 day logs of the above cronjob will look something like this:
2 am Los_Angeles time, restarting the zombieApp
2019-11-09T10:00:00.945Z 'App restarted!!!'
pm2 list
┌──────────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────┬───────────┬──────────┐
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ watching │
├──────────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────┼───────────┼──────────┤
│ zombieApp │ 0 │ fork │ 5011 │ online │ 146 │ 1s │ 33% │ 37.6 MB │ disabled │
│ someOtherApp │ 1 │ fork │ 5351 │ online │ 0 │ 4M │ 0% │ 19.5 MB │ disabled │
└──────────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────┴───────────┴──────────┘
Use `pm2 show <id|name>` to get more details about an app
2 am Los_Angeles time, restarting the zombieApp
2019-11-10T10:00:00.775Z 'App restarted!!!'
pm2 list
┌──────────────┬────┬──────┬───────┬────────┬─────────┬────────┬─────┬───────────┬──────────┐
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ watching │
├──────────────┼────┼──────┼───────┼────────┼─────────┼────────┼─────┼───────────┼──────────┤
│ zombieApp │ 0 │ fork │ 32700 │ online │ 147 │ 1s │ 0% │ 33.9 MB │ disabled │
│ someOtherApp │ 1 │ fork │ 5351 │ online │ 0 │ 4M │ 0% │ 14.9 MB │ disabled │
└──────────────┴────┴──────┴───────┴────────┴─────────┴────────┴─────┴───────────┴──────────┘
Use `pm2 show <id|name>` to get more details about an app
2 am Los_Angeles time, restarting the zombieApp
2019-11-11T10:00:02.586Z 'App restarted!!!'
pm2 list
┌──────────────┬────┬──────┬──────┬────────┬─────────┬────────┬──────┬───────────┬──────────┐
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ watching │
├──────────────┼────┼──────┼──────┼────────┼─────────┼────────┼──────┼───────────┼──────────┤
│ zombieApp │ 0 │ fork │ 3105 │ online │ 148 │ 0s │ 100% │ 35.1 MB │ disabled │
│ someOtherApp │ 1 │ fork │ 5351 │ online │ 0 │ 4M │ 0% │ 18.8 MB │ disabled │
└──────────────┴────┴──────┴──────┴────────┴─────────┴────────┴──────┴───────────┴──────────┘
Use `pm2 show <id|name>` to get more details about an app
See also
- Node JS Mongo Client for Atlas Data API
- SignatureDoesNotMatch: The request signature we calculated does not match the signature you provided. Check your key and signing method.
- Exactly Same Query Behaving Differently in Mongo Client and Mongoose
- MongoDB Single Update Query to Change the Field Name in All Matching Documents of the Collection
- AWS Layer: Generate nodejs Zip Layer File Based on the Lambda's Dependencies
- In Node JS HTML to PDF conversion, Populate Images From URLs
- Convert HTML to PDF in Nodejs