Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to only restart node process with PM2 if exit code != 0

Tags:

node.js

pm2

I'm using pm2 to manage a node process. Currently, pm2 restarts the node process even if it finishes cleanly (with exit code 0). I don't want that to happen.

Instead I only want PM2 to restart the app when the node process exits with a code != 0.

How to do this?

The pm2 logs might be useful:

PM2        | App [xxx] with id [0] and pid [44797], exited with code [0] via signal [SIGINT]
PM2        | Starting execution sequence in -fork mode- for app name:xxx id:0
PM2        | App name:xxx id:0 online

EDIT:

Seems that starting process in cluster-mode works as I expect. I.e.: restarts only happen on exit-codes !=0.

Still starting in fork-mode gives the unexpected behavior as described above.

like image 550
Geert-Jan Avatar asked Apr 25 '17 14:04

Geert-Jan


2 Answers

Late to this thread, but I believe pm2 support this now. Check out https://pm2.keymetrics.io/docs/usage/restart-strategies/ and the section "Skip Auto Restart For Specific Exit Codes"

Edit: Sorry, this is not the solution yet. There is an open issue related to this pm2 option here: https://github.com/Unitech/pm2/issues/5208. From the looks of it I don't expect it to be resolved anytime soon. So the above option should work but I don't think it does at the moment with the current version of pm2 as of this writing (5.1.12)

like image 168
stoic_monk Avatar answered Sep 21 '22 18:09

stoic_monk


I have looked at the code of pm2

https://github.com/Unitech/pm2/blob/6090b0971abca6fcb2d796e560f2a72b81ab5707/lib/God.js

And it doesn't seems to have any logic in terms of not starting a process on a successful exit. The feature you are asking for doesn't exists. It is same for cluster as well as fork mode.

You can test that using test.js

setTimeout(()=>process.exit(), 2000);

Fork mode

$ pm2 start test.js && sleep 5
[PM2] Starting /Users/tarunlalwani/Documents/Projects/SO/pm2exit/test.js in fork_mode (1 instance)
[PM2] Done.
┌──────────┬────┬─────────┬──────┬──────┬────────┬─────────┬────────┬─────┬──────────┬──────────────┬──────────┐
│ App name │ id │ version │ mode │ pid  │ status │ restart │ uptime │ cpu │ mem      │ user         │ watching │
├──────────┼────┼─────────┼──────┼──────┼────────┼─────────┼────────┼─────┼──────────┼──────────────┼──────────┤
│ test     │ 0  │ N/A     │ fork │ 5889 │ online │ 0       │ 0s     │ 0%  │ 9.4 MB   │ tarunlalwani │ disabled │
└──────────┴────┴─────────┴──────┴──────┴────────┴─────────┴────────┴─────┴──────────┴──────────────┴──────────┘
 Use `pm2 show <id|name>` to get more details about an app
$ pm2 logs
PM2        | 2019-08-18T11:40:23: PM2 log: App [test:0] exited with code [0] via signal [SIGINT]
PM2        | 2019-08-18T11:40:23: PM2 log: App [test:0] starting in -fork mode-
PM2        | 2019-08-18T11:40:23: PM2 log: App [test:0] online
PM2        | 2019-08-18T11:40:25: PM2 log: App [test:0] exited with code [0] via signal [SIGINT]
PM2        | 2019-08-18T11:40:25: PM2 log: App [test:0] starting in -fork mode-
PM2        | 2019-08-18T11:40:25: PM2 log: App [test:0] online

$ pm2 delete test
$ pm2 start test.js -i 2&& sleep 5
[PM2] Starting /Users/tarunlalwani/Documents/Projects/SO/pm2exit/test.js in cluster_mode (2 instances)
[PM2] Done.
┌──────────┬────┬─────────┬─────────┬──────┬────────┬─────────┬────────┬─────┬───────────┬──────────────┬──────────┐
│ App name │ id │ version │ mode    │ pid  │ status │ restart │ uptime │ cpu │ mem       │ user         │ watching │
├──────────┼────┼─────────┼─────────┼──────┼────────┼─────────┼────────┼─────┼───────────┼──────────────┼──────────┤
│ test     │ 0  │ N/A     │ cluster │ 5993 │ online │ 0       │ 0s     │ 0%  │ 27.6 MB   │ tarunlalwani │ disabled │
│ test     │ 1  │ N/A     │ cluster │ 5994 │ online │ 0       │ 0s     │ 0%  │ 20.8 MB   │ tarunlalwani │ disabled │
└──────────┴────┴─────────┴─────────┴──────┴────────┴─────────┴────────┴─────┴───────────┴──────────────┴──────────┘
 Use `pm2 show <id|name>` to get more details about an app

$ pm2 logs
PM2      | App name:test id:0 disconnected
PM2      | App [test:0] exited with code [0] via signal [SIGINT]
PM2      | App [test:0] starting in -cluster mode-
PM2      | App name:test id:1 disconnected
PM2      | App [test:1] exited with code [0] via signal [SIGINT]
PM2      | App [test:1] starting in -cluster mode-
PM2      | App [test:0] online
PM2      | App [test:1] online
PM2      | App name:test id:0 disconnected
PM2      | App [test:0] exited with code [0] via signal [SIGINT]
PM2      | App [test:0] starting in -cluster mode-
PM2      | App name:test id:1 disconnected
PM2      | App [test:1] exited with code [0] via signal [SIGINT]
PM2      | App [test:1] starting in -cluster mode-
PM2      | App [test:0] online
PM2      | App [test:1] online
PM2      | App name:test id:0 disconnected

$ pm2 delete test

Alternative

As an alternative you can use Supervisord

You can use the exitcodes in the configuration file

http://supervisord.org/configuration.html

The list of “expected” exit codes for this program used with autorestart. If the autorestart parameter is set to unexpected, and the process exits in any other way than as a result of a supervisor stop request, supervisord will restart the process if it exits with an exit code that is not defined in this list.

like image 28
Tarun Lalwani Avatar answered Sep 17 '22 18:09

Tarun Lalwani