How can I restart a Node.js app from within itself (programmatically)? - node.js

How can I create an app that can restart itself? I want to create an app that sets up a web-admin which can restart itself. Is this possible? If so, how? I was thinking this might be possible with the process global variable that is built into node.

LK"I
It is possible without external dependencies:
console.log("This is pid " + process.pid);
setTimeout(function () {
process.on("exit", function () {
require("child_process").spawn(process.argv.shift(), process.argv, {
cwd: process.cwd(),
detached : true,
stdio: "inherit"
});
});
process.exit();
}, 5000);
source : https://gist.github.com/silverwind/d0802f7a919ae86ff25e

I have run Forever several times and it is easy to get started with. Check it out at: https://github.com/nodejitsu/forever

I know it's a little late to reply however I had a similar requirement. I wanted to restart my node process whenever I made a configuration change. I'm using pm2 to manage my node processes so it turned out to be really easy.
After making a configuration change, i execute process.exit() from within the node process. As far as I can see, the process exits then pm2 restarts the process fine.
Not sure yet if there are any side effects but it seems to be working fine for me right now.

you can run your app using child process and manipulate it how needed:
https://nodejs.org/api/child_process.html
use forever, pm2 or whatever thing to restart after death and kill itself with process.exit() https://nodejs.org/api/process.html

Not from the process itself but it might be useful to people that land on here.
I add it to systemd of Linux and it starts up on network.target logs the console to /var/logs/<app>.log and it restarts on failure. So you can just force a process.exit on it.
sudo touch /lib/systemd/system/<app>.service
sudo tee -a /lib/systemd/system/<app>.service > /dev/null <<EOT
[Unit]
Description=<app>
After=network.target
[Service]
Type=simple
User=$USER
ExecStart=/bin/node --prefix /home/$USER/path/to/app
Restart=on-failure # or always
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=<app>
[Install]
WantedBy=multi-user.target
EOT
sudo touch /etc/rsyslog.d/<app>.conf
sudo tee -a /etc/rsyslog.d/<app>.conf > /dev/null <<EOT
if $programname == '<app>' then /var/log/<app>.log
& stop
EOT
sudo systemctl enable <app>
sudo systemctl daemon-reload
sudo systemctl restart rsyslog
sudo systemctl start <app>

i know the question is a little old but it may help someone later :
i would suggest to use nodeJS Cluster & Worker for this purpose!
const cluster = require('cluster');
if (cluster.isMaster ?? cluster.isPrimary) {
cluster.fork();
cluster.on("exit", (worker, code) => {
console.log(`[master] worker #${worker.id} down, restarting\n`);
cluster.fork();
});
process.on("SIGINT", () => { });
} else {
console.log(`\nnew worker #${cluster.worker.id}\n`);
process.on("SIGINT", () => {
console.log(`[worker#${cluster.worker.id}] SIGINT received! dying gracefully!!\n`);
process.exit(0);
});
}
try running it with nodejs and hitting the ctrl+c combination.
it will just restart with the new code running.
you can kill the master with sending any signal other than SIGINT

create file nodemon.sh
#!/usr/bin/env bash
while true; do
sleep 20
echo "// nodemon $(date)" >config.js
done
permition sudo chmod +x nodemon.sh
run it
./nodemon.sh

Yes, upstart will restart your process without a nodemon.
npm install -g nodemon
sudo nodemon server.js
nodemon will watch the files in the directory that nodemon was started, and if they change, it will automatically restart your node application.

Related

Restart an external process from within a nodejs app (linux)

Say that I am running a process from the command line (NOT a nodejs app):
myProcess doSomething --withParam1
I am also running a nodejs app that connects to this process (rpc).
node myApp
myProcess will randomly silently fail to work properly without crashing and myApp will detect it. I need myApp to be able to restart myProcess (kill it and start it again). After I restarted myProcess, myApp will also restart itself using pm2 (I am already handling the pm2 restart part for the nodejs app - my issue is that I cannot use pm2 to restart myProcess since it is not a nodejs app). Also, I cannot change the code of myProcess since it is a 3rd party software.
How can I restart the external process from my nodejs app?
I ended up using process.kill to kill the process and nodejs child process to restart it.
To find the pid of the process before killing it, I used this:
const childProcess = require('child_process');
function printPid() {
childProcess.exec('pidof -s myProcess', function(error, stdout, stderr) {
if (error) {
console.log(error);
} else {
console.log(stdout);
}
});
}

How can a NodeJS app restart itself as sudo?

I've got a NodeJS app that needs to run as superuser. The user running this (should) have sudo privileges. Therefore they can easily run the app with "sudo node ...". For convenience, I would like the app to restart itself with sudo if it's not running as root.
Reading NodeJs execute command in background and forget, I have tried the following:
const isroot = process.getuid && process.getuid() === 0;
if (!isroot) {
console.log("Must be running as superuser! Restarting with sudo.");
spawn("sudo", process.argv, {
stdio: "inherit",
detached: true
}).unref();
process.exit(0);
}
However, this doesn't work as the user needs to enter their password and, despite setting stdio to inherit, I get the error:
sudo: no tty present and no askpass program specified
Can anyone see what I'm doing wrong, and is there a more obvious solution?
Thanks for any suggestions.

How to start nodejs application automatically on openwrt - Arduino Yun -

I am trying to have a nodejs application start automatically on system boot. Basically all I need is to run the command node /dir/app.
I am using openwrt on an Arduino Yun. And have tried a couple things.
On the openwrt website it said I can do this. https://wiki.openwrt.org/inbox/procd-init-scripts :
#!/bin/sh /etc/rc.common
USE_PROCD=1
start_service() {
procd_open_instance
procd_set_param command node ///www/www-blink.js
procd_close_instance
}
I have also tried changing the dir to /www/www-blink.js not ///
However i'm not sure what i'm doing wrong as nothing comes up when I try run it with /etc/init.d/node-app start I am obviously writing the code wrong but i'm not sure what it should exactly look like.
The other thing I have tried is the node modules forever and forever-service.
I downloaded them on my computer using npm install -g forever and forever-service aswell. I transfered them to usr/lib/node_modules on my arduino yun. However when I try to use and forever(-service) commands it says
-ash: forever: not found
I have tried a couple other things, however nothing has worked. Any help would be greatly appreciated.
-- I also need to be able to start my express script with npm start not node app but I guess the first thing is getting it to work at all.
you can put the starting command (node /dir/app &)in the /etc/rc.local script. This will start your nodejs application automatically on system boot.
OpenWRT procd has a "respawn" parameter, which will restart a service that exits or crashes.
# respawn automatically if something died, be careful if you have an
# alternative process supervisor if process dies sooner than respawn_threshold,
# it is considered crashed and after 5 retries the service is stopped
procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}
So, you cold just add:
procd_set_param respawn 60 5 5
or something like that to your OpenWRT procd initscript. This 60 5 5 means it will wait 5s between respawns (middle parameter), and if it respanws more than 5 times (last parameter) in 60s (first parameter), it will disable the service ("restart loop" detected).
Refer to this page for more information:
https://openwrt.org/docs/guide-developer/procd-init-scripts
You need to execute your node application like a Linux Service.
Upstart is perfect for this task
Upstart is an event-based replacement for the /sbin/init daemon which handles starting of tasks and services during boot, stopping them during shutdown and supervising them while the system is running.
If you have an app like this (for example):
// app.js
var express = require('express')
var app = express()
var port = process.env.PORT
app.get('/', function(req, res) {
res.send('Hello world!')
})
app.listen(port)
With a package.json like this:
{
"name": "my-awesome-app",
"version": "1.0.0",
"dependencies": {
"express": "^4.13.3"
},
"scripts": {
"start": "node app.js"
}
}
We create a upstart configuration file called myAwesomeApp.conf with the following code:
start on runlevel [2345]
stop on runlevel [!2345]
respawn
respawn limit 10 5
setuid ubuntu
chdir /opt/myAwesomeApp.conf
env PORT=3000
exec npm start
To finish, put your application (app.js and package.json) in the /opt/myAwesomeApp.conf and copy the configuration file myAwesomeApp.conf in /etc/init/
This is all, now you just need to run service myAwesomeApp start to run your node application as a service
I've never used procd before, but it likely needs the full path to node (e.g., /usr/bin/node). You'd need to make the line something like procd_set_param command /usr/bin/node /www/www-blink.js, assuming the file you want to run is /www/www-blink.js. You can locate node by running which node or type -a node.

How to run node js server as a daemon process?

I am using Ionic framework and nodejs for one app. All nodejs files are in linux server. I am starting the nodejs server using 'npm start &' command through putty. But the problem is if I close putty the server is getting stopped after sometime. I tried 'nohup npm start &'. But still I am facing the same issue. How to start this as a daemon process..?
You can use pm2 for production.
To install pm2 :
npm install pm2 -g
To start an application simply just run :
pm2 start app.js
You can check logs via:
pm2 logs
For more options just checkout their readme files on github repo.
This is adaptation of daemon module:
const child_process = require('child_process')
function child(exe, args, env) {
const child = child_process.spawn(exe, args, {
detached: true,
stdio: ['ignore', 'ignore', 'ignore'],
env: env
})
child.unref()
return child
}
module.exports = function(nodeBin) {
console.log('Daemonize process')
if (process.env.__daemon) {
return process.pid
}
process.env.__daemon = true
var args = [].concat(process.argv)
var node = args.shift()
var env = process.env
child(node, args, env)
return process.exit()
}
Usage:
const daemon = require('daemon')
daemon()
app.listen(...)
https://wiki.unix7.org/node/daemon-sample
For creating true daemons (a process not attached to any tty) you can use one of the several daemon modules available on npm.
A quick search gave me this: https://www.npmjs.com/package/daemon
Interestingly, the module above works using pure javascript and node.js built-in modules without requiring any C extensions. It works by exploiting how child_process works in newer versions of node (> 0.9).
either use PM2/forever & nginx for managing the services well. [RECOMMENDED]
or you can run by the default OS services. I'm using ubuntu 20.04 amd64 on ec2-t2.micro and everything is preinstall with image.
# TO Run the service on port 80 as deamon thread
sudo PORT=80 nohup node server.js &
#To run the service on 3000 port and point to 80.
PORT=3000 nohup node server.js &
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000
# to kill the process run
ps -ef | grep "node"
kill -9 <pid>

How to stop app that node.js express 'npm start'

You build node.js app with express v4.x then start your app by npm start. My question is how to stop the app? Is there npm stop?
EDIT to include the error when implement npm stop
/home/nodetest2# npm stop
> nodetest2#0.0.1 stop /home/nodetest2
> pkill -s SIGINT nodetest2
pkill: invalid argument for option 's' -- SIGINT
npm ERR! nodetest2#0.0.1 stop: `pkill -s SIGINT nodetest2`
npm ERR! Exit status 2
Yes, npm provides for a stop script too:
npm help npm-scripts
prestop, stop, poststop: Run by the npm stop command.
Set one of the above in your package.json, and then use npm stop
npm help npm-stop
You can make this really simple if you set in app.js,
process.title = myApp;
And, then in scripts.json,
"scripts": {
"start": "app.js"
, "stop": "pkill --signal SIGINT myApp"
}
That said, if this was me, I'd be using pm2 or something the automatically handled this on the basis of a git push.
All the other solutions here are OS dependent. An independent solution for any OS uses socket.io as follows.
package.json has two scripts:
"scripts": {
"start": "node server.js",
"stop": "node server.stop.js"
}
server.js - Your usual express stuff lives here
const express = require('express');
const app = express();
const server = http.createServer(app);
server.listen(80, () => {
console.log('HTTP server listening on port 80');
});
// Now for the socket.io stuff - NOTE THIS IS A RESTFUL HTTP SERVER
// We are only using socket.io here to respond to the npmStop signal
// To support IPC (Inter Process Communication) AKA RPC (Remote P.C.)
const io = require('socket.io')(server);
io.on('connection', (socketServer) => {
socketServer.on('npmStop', () => {
process.exit(0);
});
});
server.stop.js
const io = require('socket.io-client');
const socketClient = io.connect('http://localhost'); // Specify port if your express server is not using default port 80
socketClient.on('connect', () => {
socketClient.emit('npmStop');
setTimeout(() => {
process.exit(0);
}, 1000);
});
Test it out
npm start (to start your server as usual)
npm stop (this will now stop your running server)
The above code has not been tested (it is a cut down version of my code, my code does work) but hopefully it works as is. Either way, it provides the general direction to take if you want to use socket.io to stop your server.
On MAC OS X(/BSD):
you can try to use the lsof (list open files) command
$ sudo lsof -nPi -sTCP:LISTEN
and so
$ kill -9 3320
When I tried the suggested solution I realized that my app name was truncated. I read up on process.title in the nodejs documentation (https://nodejs.org/docs/latest/api/process.html#process_process_title) and it says
On Linux and OS X, it's limited to the size of the binary name plus the length of the command line arguments because it overwrites the argv memory.
My app does not use any arguments, so I can add this line of code to my app.js
process.title = process.argv[2];
and then add these few lines to my package.json file
"scripts": {
"start": "node app.js this-name-can-be-as-long-as-it-needs-to-be",
"stop": "killall -SIGINT this-name-can-be-as-long-as-it-needs-to-be"
},
to use really long process names. npm start and npm stop work, of course npm stop will always terminate all running processes, but that is ok for me.
Check with netstat -nptl all processes
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:27017 0.0.0.0:* LISTEN 1736/mongod
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1594/sshd
tcp6 0 0 :::3977 :::* LISTEN 6231/nodejs
tcp6 0 0 :::22 :::* LISTEN 1594/sshd
tcp6 0 0 :::3200 :::* LISTEN 5535/nodejs
And it simply kills the process by the PID reference.... In my case I want to stop the 6231/nodejs so I execute the following command:
kill -9 6231
This is a mintty version problem alternatively use cmd. To kill server process just run this command:
taskkill -F -IM node.exe
If you've already tried ctrl + c and it still doesn't work, you might want to try this. This has worked for me.
Run command-line as an Administrator. Then run the command below to find the processID (PID) you want to kill. Type your port number in <yourPortNumber>
netstat -ano | findstr :<yourPortNumber>
Then you execute this command after you have identified the PID.
taskkill /PID <typeYourPIDhere> /F
Kudos to #mit $ingh from http://www.callstack.in/tech/blog/windows-kill-process-by-port-number-157
kill $(lsof -t -i :PORT_TO_KILL)
simplified version. Simple copy paste with the port to kill ex.5000
For windows machine (I'm on windows 10), if CTRL + C (Cancel/Abort) Command on cli doesn't work, and the screen shows up like this:
Try to hit ENTER first (or any key would do) and then CTRL + C and the current process would ask if you want to terminate the batch job:
Perhaps CTRL+C only terminates the parent process while npm start runs with other child processes. Quite unsure why you have to hit that extra key though prior to CTRL+ C, but it works better than having to close the command line and start again.
A related issue you might want to check: https://github.com/mysticatea/npm-run-all/issues/74
Here's another solution that mixes ideas from the previous answers. It takes the "kill process" approach while addressing the concern about platform independence.
It relies on the tree-kill package to handle killing the server process tree. I found killing the entire process tree necessary in my projects because some tools (e.g. babel-node) spawn child processes. If you only need to kill a single process, you can replace tree-kill with the built-in process.kill() method.
The solution follows (the first two arguments to spawn() should be modified to reflect the specific recipe for running your server):
build/start-server.js
import { spawn } from 'child_process'
import fs from 'fs'
const child = spawn('node', [
'dist/server.js'
], {
detached: true,
stdio: 'ignore'
})
child.unref()
if (typeof child.pid !== 'undefined') {
fs.writeFileSync('.server.pid', child.pid, {
encoding: 'utf8'
})
}
build/stop-server.js
import fs from 'fs'
import kill from 'tree-kill'
const serverPid = fs.readFileSync('.server.pid', {
encoding: 'utf8'
})
fs.unlinkSync('.server.pid')
kill(serverPid)
package.json
"scripts": {
"start": "babel-node build/start-server.js",
"stop": "babel-node build/stop-server.js"
}
Note that this solution detaches the start script from the server (i.e. npm start will return immediately and not block until the server is stopped). If you prefer the traditional blocking behavior, simply remove the options.detached argument to spawn() and the call to child.unref().
In case your json file does not have a script to stop the app, an option that I use is just by pressing ctrl+C on the cmd.
If is very simple, just kill the process..
localmacpro$ ps
PID TTY TIME CMD
5014 ttys000 0:00.05 -bash
6906 ttys000 0:00.29 npm
6907 ttys000 0:06.39 node /Users/roger_macpro/my-project/node_modules/.bin/webpack-dev-server --inline --progress --config build/webpack.dev.conf.js
6706 ttys001 0:00.05 -bash
7157 ttys002 0:00.29 -bash
localmacpro$ kill -9 6907 6906
You can use pm2
https://pm2.keymetrics.io/docs/usage/quick-start/
after installation just type in terminal
pm2 start app.js
and then
pm2 stop 0 to stop your server
All (3) solotion is :
1- ctlr + C
2- in json file
wreite a script that stop
"scripts": {
"stop": "killall -SIGINT this-name-can-be-as-long-as-it-needs-to-be"
},
*than in command write // npm stop //
3- Restart the pc
For production environments you should use Forever.js
It's so util for start and stop node process, you can list apps running too.
https://github.com/foreverjs/forever
You have to press combination ctrl + z
My os is Ubuntu

Resources