Stop node server from another file - node.js

I have the following two files.
file1.js and file2.js
From file1.js, I start a node server that exists in files2.js by using Node exec from child process.
What I would like to do is, start the server that exists file2.js from file1.js by calling exec or spawn method from child_process. Stop it after 10s or so and restart the server again. How could I achieve this?
What I've tried is that, after I started the server, I called process.exit() and then tried to execute the exec function again, but since the process has exited, the second call to exec never actually reached.
I want to achieve this without using any external package though.

One way to do this is setTimeout():
const { exec } = require('child_process');
let stopped = false;
exec('command to start the server in file two', (err, stdout, stderr) => {
if (err) {
// handle error
} else {
// do stuff
}
});
setTimeout(function(){
exec('stop the server in file two', (err, stdout, stderr)=>{
stopped = true;
if(err){
// handle error
} else {
// do stuff
}
})
}, 10000);
if(stopped) {
exec('start server again', (err, stdout, stderr)=>{
stopped = false;
if(err){
// handle error
} else {
// do stuff
}
})
}

Related

Run Bash-Script within Electron App using child_process.exec

I'm struggling with running a bash-script within main.html.
const exec = require("child_process").exec;
// Execute bash script
exec("/c/workspace/_edu_zone/Proxy_Manager/filemover.sh", shellCallback);
// Callback
function shellCallback(error, stdout, stderr) {
console.log(error, stdout)
}
I'm always getting the error: no such file or directory. What am i doing wrong?
Any help is highly appreciated.
change
/c/workspace/_edu_zone/Proxy_Manager/filemover.sh
to
c:/workspace/_edu_zone/Proxy_Manager/filemover.sh
or
your could try using node-powershell to execute the command directly
const shell = require('node-powershell')
let ps = new shell({
executionPolicy: 'Bypass',
noProfile: true
});
function lunchnode() {
process.stdout.write('logging');
ps.addCommand('node run.js')
ps.invoke()
.then(function (output) {
process.stdout.write(output)
}).catch(function (err) {
process.stdout.write(err)
ps.dispose()
})
}

How to kill node.exe child process?

I have the following piece of code with the "npm start" argument starting a node server instance :
const childProcess = require("child_process");
// running server before tests
before(function(done) {
childProcess.exec(["npm start"], function(err, out, code) {
if (err instanceof Error)
throw err;
process.stderr.write(err);
process.stdout.write(out);
process.exit();
});
setTimeout(done, 5000);
});
//run tests
require("./customer-individual.js");
require("./customer-organization.js");
After tests run the node server instance is still running somewhere as a background process . How can i kill it ?
You can use the following:
const child = childProcess.exec(["npm start"], function(err, out, code) {
// ...
});
child.kill(); // same as child.kill('SIGTERM');
console.log(child.killed); // will log true
Or any other signal, please refer to the docs: https://nodejs.org/api/child_process.html#child_process_child_kill_signal

How to check whether node child process executes completely and is listening for requests

I have a requirement that i want to run my task after booting a http server.
But i cannot check whether the server is booted.
Instead,i used a setTimeout function to assume the server is booted with 2 seconds interval.
Could anybody,who knows a better solution,help me?
Great thanks!
My code is as follows:
// main.js
function exec(command) {
var defer = q.defer();
var child = childProcess.exec(command, function (err, stdout, stderr) {
if (err) {
return defer.reject(err);
}
});
child.stdout.pipe(process.stdout);
// TODO: find another graceful way to check child process ends
setTimeout(function () {
defer.resolve();
}, 2000);
return defer.promise;
}
exec('"' + process.execPath + '" app.js')
.then(function () {
// my task here;
console.log('my task')
});
// app.js
var http = require('http'),
server;
server = http.createServer(function (req, res) {
// serve html;
res.end('hello world');
});
server.listen(9999);
// run
$> node main.js
A good solution would be to try to connect to the webserver until it responds. Since you're using Q, you can take a look at the code from this answer, which enables you to retry an operation until it succeeds.
function retry(operation, delay) {
return operation().catch(function(reason) {
// Note: I replaced delay * 2 by delay, it will be better in your case
return Q.delay(delay).then(retry.bind(null, operation, delay));
});
}
Then you could do something like
startMyWebServer()
.then (function () {
return retry(connectToWebServer, 500).timeout(10000);
})
.then(function () {
console.log("Webserver ready")
})
.catch(function (err) {
console.log("Unable to contact webserver")
});
The call to retry will retry to connect to the webserver if the previous connection failed, with a delay of 500ms. If after 10s it didn't succeed, the promise will be rejected.
The connectToWebServer function should be a function that tries to connect to your webserver and returns a promise, i.e. something like
function connectToWebServer() {
var d = q.defer();
request('http://your-ip:your-port', function (err, res) {
if (err || res.statusCode != 200) {
return d.reject("Error : "+(err || "status code "+res.statusCode));
}
d.resolve();
}
return d.promise;
}

Contextify : How to catch async errors

I need to run unsafe JS script in node and be able to recover from errors.
The script can use async functions so I use contextify instead of node built in VM module.
The problem is that errors in async code in the script crash the node process.
Here is my test :
var contextify = require('contextify');
var context = {
console:{
log:function(msg){
console.log('Contextify : '+msg);
}
},
setTimeout:setTimeout
};
console.log("begin test");
contextify(context);
try{ // try to run unsafe script
//context.run("console.log('Sync user script error');nonExistingFunction();"); // works
context.run("setTimeout(function(){ console.log('Async user script error');nonExistingFunction(); },2000);"); // crash node process
}catch(err){
console.log("Recover sync user script error");
}
console.log("end test");
How can I catch async errors ?
I solved the problem by using child_process to create a thread for the script to execute in :
//main.js
var child_process = require('child_process');
var script = child_process.fork("scriptrunner.js");
script.on('error',function(err){
console.log("Thread module error " + JSON.stringify(err));
});
script.on('exit',function(code,signal){
if(code==null)
console.log("Script crashed");
else console.log("Script exited normally");
});
script.send("setTimeout(function(){ console.log('Async user script error');nonExistingFunction(); },2000);");
//scriptrunner.js
var contextify = require('contextify');
var context = {
console:{
log:function(msg){
console.log('Contextify : '+msg);
}
},
setTimeout:setTimeout
};
contextify(context);
process.on('message', function(js) {
try{
context.run(js);
}catch(err){
console.log("Catch sync user script error " + err);
}
});
So now if the script crashes it crash its own process and not the main node process. The downside is that I can't pass complex object (such as my context) between my main process and the script's thread, I need to find a workaround for that.

How do I cleanly shutdown mongodb from node.js?

I am running mongodb as a child process from node.js and require to shut down and restart on demand. using Child_Process.kill("SIGINT") would appear to be the correct way but but it leaves mongo in a confused state which won't restart until repaired (or the lockfile is deleted) Is there a better way to do this?
Thanks,
Andy
Doing kill("SIGINT") cause the database to shut down without going through the required steps and could lead to corrupt data files. So i would not recommend do this.
Normal way to stop database is send command { "shutdown" : 1 } or db.shutdownServer() from mongodb shell, but I don't know exactly how to do it from node.js driver.
you can try something like this:
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect("mongodb://localhost:27017/admin", function(err, db) {
if (err) {
console.log('mongodb is not running');
process.exit(0);
}
else {
db.command({
shutdown : 1
}, function(err, result) {
console.log('shutting down mongodb - ', err.message);
process.exit(0);
});
}
});
you could end a mongodb process using nodeJS on mac
1) save the script below to a script.js
'use strict'
const exec = require('child_process').execSync;
function killport(port) {
var processId = null
try {
processId = exec(`lsof -t -i:${port}`);
} catch (e) {
console.log("could not catch");
}
if (processId !== null) { // if exists kill
try{
if(exec(`kill ${processId}`)){
console.log("closed");
}
} catch(e){
console.log("error executing");
}
}
}
killport(27017);
2) run node script.js

Resources