Is there a way to restart pm2 process using cron but only if it's not already running?

I want to restart my Node.Js app using PM2 through

pm2 restart app.js

using crontab but ONLY if the app is not already running (e.g. if my server crashed and restarted and pm2 didn’t restart).

the command above restarts it anyway even if it’s running.

How do I fix it?

UPDATE

I do not want my app to restart if it’s already running. I want it to restart only if it’s listed as “stopped” or if it is not running.
Some suggestions offer to write a bash script, but what would it be? I tried the options below, but they either don’t work or restart the app even if it’s running.

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

The better way of doing it is use the pm2 startup command

http://pm2.keymetrics.io/docs/usage/startup/

To get the automatically-configured startup script for your machine you need to type this command:

# Detect available init system, generate configuration and enable startup system
pm2 startup

You can specify the platform you use by yourself if you want to (where platform can be either one of the cited above):

pm2 startup [ubuntu | ubuntu14 | ubuntu12 | centos | centos6 | arch | oracle | amazon | macos | darwin | freebsd | systemd | systemv | upstart | launchd | rcd | openrc]

The output of this command can be a recommendation of the line to copy/paste with all environment variables and options configured for you.

Example:

[PM2] You have to run this command as root. Execute the following command:
sudo su -c “env PATH=$PATH:/home/unitech/.nvm/versions/node/v4.3/bin pm2 startup -u –hp

You simply have to copy/paste the line PM2 gives you and the startup script will be configured for your OS.

Once you run the sudo pm2 startup. It will create the systemctl service. You can check the status of the same using

systemctl status pm2-root

By default the service is not configure to restart automatically. You will run the below commands

sudo mkdir -p /etc/systemd/system/pm2-root.service.d

and then create a file name 10_auto_restart_pm2.conf with below content

[Service]
Restart=always
RestartSec=3

After that execute

systemctl daemon-reload
systemctl restart pm2-service

Now let’s test the auto restart part

$ systemctl status pm2-root.service
● pm2-root.service - PM2 process manager
   Loaded: loaded (/etc/systemd/system/pm2-root.service; enabled; vendor preset: enabled)
  Drop-In: /etc/systemd/system/pm2-root.service.d
           └─10_auto_restart_pm2.conf
   Active: active (running) since Wed 2018-02-28 16:52:19 UTC; 11s ago
     Docs: https://pm2.keymetrics.io/
  Process: 5014 ExecStop=/usr/local/lib/node_modules/pm2/bin/pm2 kill (code=exited, status=0/SUCCESS)
  Process: 5022 ExecStart=/usr/local/lib/node_modules/pm2/bin/pm2 resurrect (code=exited, status=0/SUCCESS)
 Main PID: 5031 (PM2 v2.10.1: Go)
    Tasks: 9
   Memory: 24.3M
      CPU: 460ms
   CGroup: /system.slice/pm2-root.service
           └─5031 PM2 v2.10.1: God Daemon (/home/vagrant/.pm2)

Now we kill the process manually and wait for 3 seconds

$ kill -9 5031
$ sleep 3
$ systemctl status pm2-root.service
● pm2-root.service - PM2 process manager
   Loaded: loaded (/etc/systemd/system/pm2-root.service; enabled; vendor preset: enabled)
  Drop-In: /etc/systemd/system/pm2-root.service.d
           └─10_auto_restart_pm2.conf
   Active: active (running) since Wed 2018-02-28 16:52:55 UTC; 641ms ago
     Docs: https://pm2.keymetrics.io/
  Process: 5057 ExecStop=/usr/local/lib/node_modules/pm2/bin/pm2 kill (code=exited, status=0/SUCCESS)
  Process: 5081 ExecStart=/usr/local/lib/node_modules/pm2/bin/pm2 resurrect (code=exited, status=0/SUCCESS)
 Main PID: 5088 (PM2 v2.10.1: Go)
    Tasks: 9
   Memory: 24.3M
      CPU: 461ms
   CGroup: /system.slice/pm2-root.service
           └─5088 PM2 v2.10.1: God Daemon (/home/vagrant/.pm2)

As you can see the process/service was restarted automatically. No cron needed and it is how you should do it.

Solution 2

What you’re looking to do is start any stopped apps without incurring downtime. A good solution is to use the pm2 startOrReload command. This will start any stopped apps, and will reload any current apps without incurring downtime.

You’ll need a config file for the command. if you don’t currently have one you can create it using pm2 ecosystem. Make sure it points to app.js.

Then run this command in your cron job:

pm2 startOrReload <your ecosystem file>

See pm2 -h, pm2 startOrReload -h, and pm2 ecosystem -h for more options.

Solution 3

Instead of launching the pm2 process within the cron, launch a bashscript which checks if the pm2 is already running and restarts it if it’s not the case.

Edit

Try following (it might be that the pgrep expression needs to be adjusted, I don’t know the exact name of the pm2 process):

#!/bin/bash

pID=$(pgrep -x "pm2") 

if [ -n "${pID}" ];
then
    #do nothing 
    echo $pID "already running. not restarting." 
else
    # start it 
    echo "restarting"
    # put your command to start your process here
fi

Solution 4

For Linux

My use case: Run the app every 3 seconds.

Easy way:

pm2 startup This creates a command, copy and run it.

pm2 start app.js --restart-delay=3000 Each 3000 ms restart the app

pm2 save

Finally, reboot Linux and test.

For Windows

Use case: Run the app.py at every 3rd minute.

  1. https://github.com/jessety/pm2-installer

  2. pm2 start app.py --cron "*/3 * * * *" --no-autorestart --time

  3. pm2 save

Restart Windows and check.

More Info

Solution 5

Improving on @Aydin K. answer

#! /bin/bash -l

ps cax | grep PM2 > /dev/null
if [ $? -eq 0 ]; then
  echo $(date -u) - "PM2 is running."
else
  echo $(date -u) - "Restarting PM2."
  cd ~/app-location
  ~/bin/node ~/bin/pm2 start app.js
fi

Explanation

Breaking each code.

-l in #! /bin/bash -l will use your environment variables from .bashrc

ps cax | grep PM2 > /dev/null gets the number of processes with PM2 (Case-capital) since the process is named as “PM2 …”

~/bin/node ~/bin/pm2 start app.js this is a big catch. You need to use node before using pm2 commands in cron. Also you need to use the location where your node and pm2 are installed. Can be found by running which node on your shell.

The cron can be configured to run every 15 minutes (or as per your preference)

*/15 * * * * ~/amb-cron.sh >> ~/logs/pm2-process.txt`
#you can create a log for your echos.

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply