How can a NodeJS app restart itself as sudo? - node.js

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.

Related

Spawn command as sudo in NPM/Yeoman

I'm learning Yeoman and have gotten really far which is nice :), but I'm now at the point in my generator where I would like to set up a VHOST for my new project.
The way I normally create a VHOST is create a *.conf file in /etc/apache2/sites-available/, run sudo a2ensite new-site and finally sudo service apache2 reload.
How can I use generator.spawnCommand() (or anything else that works) to run my sudo commands? I assume the user would need to enter his password for the commands to run of course.
Note that I've tried the sudo npm package but it just fails silently even with the example code provided on https://www.npmjs.com/package/sudo
Maybe I've misunderstood something, but the following simple code worked fine for me:
var generators = require('yeoman-generator');
var execSync = require('child_process').execSync;
module.exports = generators.Base.extend({
touch: function () {
execSync('sudo touch /tmp/test-sudo', {
stdio: 'inherit'
});
}
});

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.

Grunt message: Fatal error: Port 35729 is already in use by another process

Grunt was working. But after moving my site's files up one directory, to sit at root, grunt stopped working:
Fatal error: Port 35729 is already in use by another process.
Would the path matter in this case? Looking at port 35729, I found that Grunt was the only process running on that port. I killed that process, confirmed that no other process was running on 35729, then ran grunt again, but still getting that same fatal error as before.
Although none of my config files changed for grunt since it was working, I thought I'd try using the "npm init" approach to create a new package.json, then run "npm install" again and confirmed it downloaded "node_modules". What else can I try?
I'm running Node v0.10.33 on Mac OS 10.10.5
Dont stop a process with Ctrl+C in the terminal.
Ctrl+Z will keep it running.
Find the process id by sudo lsof -i :35729
Then kill the process by sudo kill -9 PID
Rerun the grunt watch
Grunt watch was already running in a different project in my case. So I updated Grunt's watch task appropriately for live reload to watch on a different port.
watch: {
main: {
options: {
livereload: 35730,
livereloadOnError: false,
spawn: false
},
files: [createFolderGlobs(['*.js', '*.less', '*.html']), '!_SpecRunner.html', '!.grunt'],
tasks: [] //all the tasks are run dynamically during the watch event handler
}
}
Specified livereload:PORT
The problem is grunt-contrib-watch's live reload: https://github.com/gruntjs/grunt-contrib-watch/blob/v1.0.0/tasks/lib/livereload.js#L19
You can't have two grunt-watch with the livereload option set to true. Either set one of the livereload options to false or change the port of liverelaod to something else by setting the livereload option from true to other value than 35729, like live-reload: 1337.
See the docs for more: https://github.com/gruntjs/grunt-contrib-watch#optionslivereload
Otherwise, you can run as many grunt processes as you want.
Problem solved. Although grunt-cli is installed globally, grunt gets installed locally with the project. So when I moved my site's files up one directory, and ran grunt from that new location, I was effectively launching a second instance of grunt, which found the port already occupied of course, by the earlier instance of grunt launched before moving files.
After I killed that process, grunt ran without a problem. I wasn't able to kill it using kill -9 so I used the Mac's Activity Monitor to issue "Force Quit".
solution :
Step 1
Run command-line as an Administrator. Then run the below mention command. Type your port number in yourPortNumber:
netstat -ano | findstr : (yourPortNumber)
Step 2
Then you execute this command after identify the PID.
taskkill /PID (typeyourPIDhere) /
Enjoy Coding !

node.js child process change a directory and run the process

I try to run external application in node.js with child process like the following
var cp = require("child_process");
cp.exec("cd "+path+" && ./run.sh",function(error,stdout,stderr){
})
However when I try to run it stuck, without entering the callback
run.sh starts a server, when I execute it with cp.exec I expect it run asynchronously, such that my application doesn't wait until server termination. In callback I want to work with server.
Please help me to solve this.
cp.exec get the working directory in parameter options
http://nodejs.org/docs/latest/api/child_process.html#child_process_child_process_exec_command_options_callback
Use
var cp = require("child_process");
cp.exec("./run.sh", {cwd: path}, function(error,stdout,stderr){
});
for running script in the "path" directory.
The quotes are interpreted by the shell, you cannot see them if you just look at ps output.

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

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.

Resources