Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node.js getting SIGINT from pm2

Tags:

node.js

pm2

I'm trying to use pm2 to run my node app as a service.

Right now, starting and stopping the app works. However, I want to do a graceful shutdown.

My app already listens for SIGINT, shutdowns the server and then exits the process. However, trying to put pm2 to send the SIGINT, just causes the app to restart, like if pm2 was killing and starting it again.

This is how I create the process:

pm2 start server.js --name ProcessName --silent --kill-timeout 3000

Here's my app's code for listening the SIGINT:

process.on("SIGINT", function () {
    //graceful shutdown
    server.end().then(() => {
        process.exit();
    }).catch((err) => {
        console.error(err);
    });

});

Then to shutdown the app using pm2, I'm running:

pm2 sendSignal SIGINT ProcessName

Which, again, restarts the app.

Reading over pm2 docs, I found that pm2 will also send a shutdown event to the app, so I added:

process.on('message', function(msg) {
    if (msg == 'shutdown') {
        server.end().then(() => {
            process.exit();
        }).catch((err) => {
            console.error(err);
        });
    }
});

Which isn't working either.

Any idea how to solve this?

Thanks!

like image 471
Fede E. Avatar asked May 30 '18 14:05

Fede E.


2 Answers

If you haven't solved it yet...

Based on the information you provided, I assume you are running it on Windows.

Your app cannot catch SIGINT sent by PM2 on Windows.
shutdown message works on windows too, but it is sent only by gracefulReload command.


(update)
These are not complete solutions, but might be helpful (hopefully...)

sendSignal command calls process.kill() eventually, and some of these signals might work (haven't tried).

I also found the below method. This can gracefully shutdown a process without restarting only if autorestart option is turned off.
And then your clusters will not reload in case of an accident, so it might not be what you want though...

pm2 lets you send a custom message (reference).
Put the code below in a new file:

var pm2 = require('pm2');
var id = process.argv[2];

pm2.connect(() => {
  pm2.sendDataToProcessId({
    type: 'shutdown',
    data:{some: 'data'},
    id: id,
    topic: 'some topic'
  }, (err, res) => {
    console.log('message sent');
    pm2.disconnect();

    if(err) throw err;
  })
});

Modify the part that listens the shutdown message like below:

process.on('message', function(msg){
  if(msg == 'shutdown' || msg.type == 'shutdown'){
    // code to clean up
  }
});

And run the first file with node with id of the cluster you want to shutdown as an argument.

The reason for extra msg.type == 'shutdown' in the condition is that pm2.sendDataToProcessId() requires the argument to be an object with those keys, and does not accept simple shutdown string.

like image 168
Toraja Avatar answered Sep 23 '22 13:09

Toraja


In general pm2 stop is the right way to stop your application. However if you run appliation inside of the Docker you need to use pm2-runtime instead of pm2 which is a part of pm2 npm package and passes system SIGINT to all child processes. See http://pm2.keymetrics.io/docs/usage/docker-pm2-nodejs

like image 44
dkozlovskyi Avatar answered Sep 25 '22 13:09

dkozlovskyi