running pm2 as part of crontab script - node.js

I have a crontab command set up like below
*/2 * * * * cd dir && dir/keepalive.ksh qa >> /var/log/test/keepalive.log
the keepalive.sh script essentially calls a start script with 'test' argument which executes the following script
print "Start the following proccesses"
if [ ${ENV} == "qa" ]
then
dir="my path"
print "Start QA Server"
pm2 start ${dir}/server.js -- app-env=qa db-env=qa
fi
exit
Problem: The pm2 command never starts up the process. I also tried to use the full path of pm2 (/usr/local/bin/pm2) but still no luck. I can see the output of the print statements which means the script is getting executed as expected.
Any idea what might be going wrong?

I ran into the similar problem before and it turned out I need to prepend the pm2 command with the exact path to my node executable like this
/usr/local/bin/node /usr/local/bin/pm2 start myapp.js
So in your case, you can try
/path/to/node /usr/local/bin/pm2 start ${dir}/server.js -- app-env=qa db-env=qa
Where /path/to/node needs to be replaced with the output of which node in your terminal.

Related

Node JS run using Cron Job on AWS

I am trying to run a node script on an AWS Ubuntu server. When I log into the Ubuntu server from my terminal and run my script with the command "node dacDev.js" it works just fine. The script writes to a log file in another folder. I want to run this with a cron command on AWS, but it won't run. Here is what my cron job says.
"* * * * * /home/ubuntu/.nvm/versions/node/v13.14.0/bin/node /home/ubuntu/getmyteatime/cronjob.sh"
The file cronjob.sh contains the absolute path of the node script. It reads:
node /home/ubuntu/getmyteatime/dacDev.js
Nothing runs. What am I doing wrong?
For the node, you also need an absolute path to run any.js file. This is achievable but rather than running with node try to write a script and do the following:
echo $PATH # /path/to/env
which npm # /path/to/npm
Paste below lines when the command crontab -e is executed.
PATH=/path/to/env
* * * * * cd /path/to/app && path/to/npm run script >>/tmp/crontab.log 2>&1
>>/tmp/crontab.log 2>&1 -- means, it will log the result to this path for debugging purposes.

Can not start a script in monit

I have a script which have to run another script in background:
#!/bin/bash
( cd /var/lib/docker/volumes/hostcontrol-pipe/_data/ && ./run-pipe.sh ) &
Firstly it changes directory and runs a script. run-pipe.sh creates named pipes in its directory.
And I have a monit config file to monitor this script and to restart it if it's not running:
check program check-pipe with path /bin/bash -c "echo 'ping' > /var/lib/docker/volumes/hostcontrol-pipe/_data/host-pipe" with timeout 1 seconds
if status != 0 then
restart
start program = "/var/lib/docker/volumes/hostcontrol-pipe/_data/monit.sh"
First line checks the script is running writing to its pipe, it works.
The line "start program" doesn't work - the script doesn't run and it's abscent in the "ps ax". But I see in "sudo monit -vI":
'check-pipe' start: '/var/lib/docker/volumes/hostcontrol-pipe/_data/monit.sh'
'check-pipe' started
'check-pipe' program started
So, why monit cant run the script? I tried different variants, but cant run it. I can run it without changing directory (cd), but this is nessecary.
Actually monit could not run a script in background because where wasn't output. After adding output file it started to work.
start program = "/bin/bash -c 'cd /var/lib/docker/volumes/hostcontrol-pipe/_data && ./run-pipe.sh > 1.log &'"
Or otherwise /dev/null as output stream.

How to restart PM2 using cron?

I need to find a cron command that would restart pm2 with a process but only if it's not already running
pm2 start app.js starts the app even if it's already running.
what would be another command I could use that would only restart app.js if it's not already running and how would I write it in crontab?
There is no default way in pm2 to achieve this instead of that you can write a shell script for that.
#!/bin/bash
pm2 describe appname > /dev/null
RUNNING=$?
if [ "${RUNNING}" -ne 0 ]; then
pm2 start ./yourscriptpath
else
pm2 restart appname
fi;
Save this shell script as pm2_starter.sh and then
crontab -e
and add following there
*/30 * * * * ./home/ridham/stackoverflow/pm2_starter.sh
this will run it every 30 minutes.
Here the script will restart if app is running under pm2 and else it will start it. You are smart enough to edit that as per your use case

Shell Script not running properly

I have a linux shell script that when run from command line works perfectly but when scheduled to run via crontab, it does not give desired results.
The script is quite simple, it checks to see if mysql-proxy is running or not by checking if its pid is found using the pidof command. If found to be off, it attempts to start the proxy.
# Check if mysql proxy is off
# if found off, attempt to start it
if pidof mysql-proxy
then
echo "Proxy running."
else
echo "Proxy off ... attempting to restart"
/usr/local/mysql-proxy/bin/mysql-proxy -P 172.20.10.196:3306 --daemon --proxy-backend-addresses=172.20.10.194 --proxy-backend-addresses=172.20.10.195
if pidof mysql-proxy
then
echo "Proxy started"
else
echo "Proxy restar failed"
fi
fi
echo "==============================================="
The script is saved in a file check-sql-proxy.sh and has permissions set to 777. When I run the script from command line (sh check-sql-proxy.sh) it gives the desired output.
4066
Proxy running.
===============================================
The script is also scheduled to run every 5 minutes in crontab as
*/5 * * * * bash /root/auto-restart-mysql-proxy.sh > /dev/sql-proxy-restart-log.log
However, when I see the sql-proxy-restart-log.log file it contains the output:
Proxy off ... attempting to restart
Proxy restar failed
===============================================
It seems that pidof command fails to return the pid of the running application which brings the flow of script in else condition.
I am unable to figure out how to resolve this since when I run the script manually, it works fine.
Can anyone help what I am missing with regards to permissions or settings?
Thanks in advance.
Mudasser
Check that the shell is what you think it is (usually /bin/sh, not bash)
Also check that PATH environment variable. Usually, for cron jobs it is a good practice to fully qualify all paths to binaries, e.g.
#!/bin/bash
# Check if mysql proxy is off
# if found off, attempt to start it
if /bin/pidof mysql-proxy
etc.
Try pidof /usr/local/mysql-proxy/bin/mysql-proxy (full path to executable)
In common, try use the same command name as was used to start the instance of mysql-proxy.
The problem seems that crontab environment don't have the same environment as you.
You have 2 simple & proper solutions :
In the first lines of crontab :
PATH=/foo:/bar:/qux
SHELL=/bin/bash
or
source ~/.bashrc
in your scripts.

Automatically start forever (node) on system restart

I am using node's forever module to keep my node server running. Forever however terminates when there is a system restart. Is there any way I can automatically start the node server (with forever) when the system restarts?
I would suggest using crontab. It's easy to use.
How to
To start editing run the following replacing the "testuser" with your desired runtime user for the node process. If you choose a different user other than yourself, you will have to run this with sudo.
$ crontab -u testuser -e
If you have never done this before, it will ask you which editor you wish to edit with. I like vim, but will recommend nano for ease of use.
Once in the editor add the following line:
#reboot /usr/local/bin/forever start /your/path/to/your/app.js
Save the file. You should get some feedback that the cron has been installed.
For further confirmation of the installation of the cron, execute the following (again replacing "testuser" with your target username) to list the currently installed crons:
$ crontab -u testuser -l
Note that in my opinion, you should always use full paths when executing binaries in cron.
Also, if the path to your forever script is not correct, run which forever to get the full path.
Given that forever calls node, you may also want to provide the full path to node:
#reboot /usr/local/bin/forever start -c /usr/local/bin/node /your/path/to/your/app.js
Further Reading
crontab Man Page
Ubuntu Cron HowTo
You can use forever-service for doing this.
npm install -g forever-service
forever-service install test
This will provision app.js in the current directory as a service via forever. The service will automatically restart every time system is restarted. Also when stopped it will attempt a graceful stop. This script provisions the logrotate script as well.
Github url: https://github.com/zapty/forever-service
NOTE: I am the author of forever-service.
Install PM2 globally using NPM
npm install pm2 -g
Start your script with pm2
pm2 start app.js
generate an active startup script
pm2 startup
NOTE: pm2 startup is for startting the PM2 when the system reboots. PM2 once started, restarts all the processes it had been managing before the system went down.
In case you want to disable the automatic startup, simply use pm2 unstartup
If you want the startup script to be executed under another user, just use the -u <username> option and the --hp <user_home>:
This case is valid for Debian.
Add the following to /etc/rc.local
/usr/bin/sudo -u {{user}} /usr/local/bin/forever start {{app path}}
{{user}} replaces your username.
{{app path}} replaces your app path. For example, /var/www/test/app.js
An alternative crontab method inspired by this answer and this blog post.
1. Create a bash script file (change bob to desired user).
vi /home/bob/node_server_init.sh
2. Copy and paste this inside the file you've just created.
#!/bin/sh
export NODE_ENV=production
export PATH=/usr/local/bin:$PATH
forever start /node/server/path/server.js > /dev/null
Make sure to edit the paths above according to your config!
3. Make sure the bash script can be executed.
chmod 700 /home/bob/node_server_init.sh
4. Test the bash script.
sh /home/bob/node_server_init.sh
5. Replace "bob" with the runtime user for node.
crontab -u bob -e
6. Copy and paste (change bob to desired user).
#reboot /bin/sh /home/bob/node_server_init.sh
Save the crontab.
You've made it to the end, your prize is a reboot (to test) :)
Copied answer from the attached question.
You can use PM2, it's a production process manager for Node.js applications with a built-in load balancer.
Install PM2
$ npm install pm2 -g
Start an application
$ pm2 start app.js
If you using express then you can start your app like
pm2 start ./bin/www --name="app"
Listing all running processes:
$ pm2 list
It will list all process. You can then stop / restart your service by using ID or Name of the app with following command.
$ pm2 stop all
$ pm2 stop 0
$ pm2 restart all
To display logs
$ pm2 logs ['all'|app_name|app_id]
You need to create a shell script in the /etc/init.d folder for that. It's sort of complicated if you never have done it but there is plenty of information on the web on init.d scripts.
Here is a sample a script that I created to run a CoffeeScript site with forever:
#!/bin/bash
#
# initd-example Node init.d
#
# chkconfig: 345
# description: Script to start a coffee script application through forever
# processname: forever/coffeescript/node
# pidfile: /var/run/forever-initd-hectorcorrea.pid
# logfile: /var/run/forever-initd-hectorcorrea.log
#
# Based on a script posted by https://gist.github.com/jinze at https://gist.github.com/3748766
#
# Source function library.
. /lib/lsb/init-functions
pidFile=/var/run/forever-initd-hectorcorrea.pid
logFile=/var/run/forever-initd-hectorcorrea.log
sourceDir=/home/hectorlinux/website
coffeeFile=app.coffee
scriptId=$sourceDir/$coffeeFile
start() {
echo "Starting $scriptId"
# This is found in the library referenced at the top of the script
start_daemon
# Start our CoffeeScript app through forever
# Notice that we change the PATH because on reboot
# the PATH does not include the path to node.
# Launching forever or coffee with a full path
# does not work unless we set the PATH.
cd $sourceDir
PATH=/usr/local/bin:$PATH
NODE_ENV=production PORT=80 forever start --pidFile $pidFile -l $logFile -a -d --sourceDir $sourceDir/ -c coffee $coffeeFile
RETVAL=$?
}
restart() {
echo -n "Restarting $scriptId"
/usr/local/bin/forever restart $scriptId
RETVAL=$?
}
stop() {
echo -n "Shutting down $scriptId"
/usr/local/bin/forever stop $scriptId
RETVAL=$?
}
status() {
echo -n "Status $scriptId"
/usr/local/bin/forever list
RETVAL=$?
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
restart)
restart
;;
*)
echo "Usage: {start|stop|status|restart}"
exit 1
;;
esac
exit $RETVAL
I had to make sure the folder and PATHs were explicitly set or available to the root user since init.d scripts are ran as root.
Use the PM2
Which is the best option to run the server production server
What are the advantages of running your application this way?
PM2 will automatically restart your application if it crashes.
PM2 will keep a log of your unhandled exceptions - in this case, in a file at /home/safeuser/.pm2/logs/app-err.log.
With one command, PM2 can ensure that any applications it manages restart when the server reboots. Basically, your node application will start as a service.
ref: https://www.digitalocean.com/community/tutorials/how-to-use-pm2-to-setup-a-node-js-production-environment-on-an-ubuntu-vps
Forever was not made to get node applications running as services. The right approach is to either create an /etc/inittab entry (old linux systems) or an upstart (newer linux systems).
Here's some documentation on how to set this up as an upstart:
https://github.com/cvee/node-upstart
crontab does not work for me on CentOS x86 6.5. #reboot seems to be not working.
Finally I got this solution:
Edit: /etc/rc.local
sudo vi /etc/rc.local
Add this line to the end of the file. Change USER_NAME and PATH_TO_PROJECT to your own. NODE_ENV=production means the app runs in production mode. You can add more lines if you need to run more than one node.js app.
su - USER_NAME -c "NODE_ENV=production /usr/local/bin/forever start /PATH_TO_PROJECT/app.js"
Don't set NODE_ENV in a separate line, your app will still run in development mode, because forever does not get NODE_ENV.
# WRONG!
su - USER_NAME -c "export NODE_ENV=production"
Save and quit vi (press ESC : w q return). You can try rebooting your server. After your server reboots, your node.js app should run automatically, even if you don't log into any account remotely via ssh.
You'd better set NODE_ENV environment in your shell. NODE_ENV will be set automatically when your account USER_NAME logs in.
echo export NODE_ENV=production >> ~/.bash_profile
So you can run commands like forever stop/start /PATH_TO_PROJECT/app.js via ssh without setting NODE_ENV again.
I wrote a script that does exactly this:
https://github.com/chovy/node-startup
I have not tried with forever, but you can customize the command it runs, so it should be straight forward:
/etc/init.d/node-app start
/etc/init.d/node-app restart
/etc/init.d/node-app stop
The problem with rc.local is that the commands are accessed as root which is different than logging to as a user and using sudo.
I solved this problem by adding a .sh script with the startup commands i want to etc/profile.d. Any .sh file in profile.d will load automatically and any command will be treated as if you used the regular sudo.
The only downside to this is the specified user needs to loggin for things to start which in my situation was always the case.
I tried lots of the above answers. None of them worked for me. My app is installed in /home and as user, not as root. This probably means that when the above mentioned start scripts run, /home is not mounted yet, so the app is not started.
Then I found these instructions by Digital Ocean:
https://www.digitalocean.com/community/tutorials/how-to-use-pm2-to-setup-a-node-js-production-environment-on-an-ubuntu-vps
Using PM2 as explained was very simple and works perfectly: My virtual servers had two physical crashes since - downtime was only about a minute.
complete example crontab (located at /etc/crontab) ..
#!/bin/bash
# edit this file with .. crontab -u root -e
# view this file with .. crontab -u root -l
# put your path here if it differs
PATH=/root/bin:/root/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
# * * * * * echo "executes once every minute" > /root/deleteme
#reboot cd /root/bible-api-dbt-server; npm run forever;
#reboot cd /root/database-api-server; npm run forever;
#reboot cd /root/mailer-api-server; npm run forever;
I have found my own solution by using serve & npm as follows:
Install serve package: npm install -g serve
Then have the command serve -s /var/www/sitename to execute on reboot.
This is what works for me on my VPS.
You can use the following command in your shell to start your node forever:
forever app.js //my node script
You need to keep in mind that the server on which your app is running should always be kept on.

Resources