Need to run a NodeJs application from another NodeJs application - node.js

I have a NodeJs application running in the following directory
First Application's Path '/users/user1/projects/sampleProject' which is running at 3000 port.
Second Application's Path '/users/user1/demoProjects/demo1' which is going to run at 5000 port on triggering the router function from first application.
The second NodeJs application is not yet started(It will run at port 5000). It need to run independently on hitting a router function in the first NodeJs Application which is running on port 3000 ie(http://localhost:3000/server/startServer). I'm new to NodeJs child processes, Kindly correct me if i'm wrong. And suggest me a right way to do it. Thanks
Start another node application using node.js?
I have tried it like below
// First NodeJs application
import { exec } from "child_process";
router.get('/startServer', async (req, res, next) => {
console.log("Initiated request")
let startServerInstance = 'cd "/users/user1/demoProjects/demo1" && npm run dev'; // path for the second NodeJs application
console.log("Server instance path => " + startServerInstance)
try {
// exec from child process, Spawns a shell then executes the command within that shell
let child = exec(startServerInstance, function (err, stdout, stderr) {
if (err) throw err;
else {
console.log("result ")
res.json({
status: 'success'
});
}
});
} catch (error) {
res.json({
status: 'error',
message: error
});
}
});
The above code executes the command and triggered the second application to run in background but it doesn't return anything. Either error or success result.

You need to use stout and stderror to check other server logs. Also your code is not correct. If you use if without {} it will not go to else statement. That is why you don't see 'result' text in console.
import {
exec
} from "child_process";
router.get('/startServer', async (req, res, next) => {
console.log("Initiated request")
let startServerInstance = 'cd "/users/user1/demoProjects/demo1" && npm run dev'; // path for the second NodeJs application
console.log("Server instance path => " + startServerInstance)
try {
// exec from child process, Spawns a shell then executes the command within that shell
let child = exec(startServerInstance, function(err) {
if (err) throw err;
console.log("Server started");
});
child.stdout.on('data', (data) => {
// this is new server output
console.log(data.toString());
});
child.stderr.on('data', (data) => {
// this is new server error output
console.log(data.toString());
});
res.json({
status: 'success'
});
} catch (error) {
res.json({
status: 'error',
message: error
});
}
});

Child process callback is only called once the process terminates. If the process keeps running, callback is not triggered.
Explained here - https://nodejs.org/docs/latest-v10.x/api/child_process.html#child_process_child_process_exec_command_options_callback

Related

Terminate a process from node js

//Run commands to start navigation and robot_pose package
nav = spawn("roslaunch",["turtlebot3_navigation", "turtlebot3_navigation.launch","map_file:=$HOME/catkin_ws/src/robot-rosbridge/server/newmap.yaml"], { shell: true })
nav.stdout.on("data", data => {
console.log(`stdout: ${data}`);
});
nav.on('error', (error) => {
console.log(`error: ${error.message}`);
res.sendStatus(500)
});
Well here I'm trying to terminate the nav process using "nav.kill()" but the process is not terminating .Earlier while I was using spawn without { shell: true } nav.kill() worked fine but now its not working.
On the whole I'm trying to spawn a process when a specific route is requested and terminate it when another route is requested
i.e.,
const express = require('express')
const app = express()
app.get("/start", (req, res) => {
//spawn a process
});
app.get("/stop", (req, res) => {
//kill process
});
I'm confused as to how spawn is working. Can anyone suggest a solution and the working of the spawn function or any better alternative.
Thanks in advance.

nodejs: Start server and look for string "server started at 127.0.0.1:8000" and then start the tests

I am starting the server from my NodeJS script and then want to execute my tests. But when I start the server the server start process doesn't return as it is running and control is not returned back. The server starts and the app can be accessed on http://localhost:8000.
trying to start the server and then monitor the stdout of the runserver process and look for a match "Starting server at 127.0.0.1:8000" and then proceed to run the tests.
Is there any way it can be done using exec or spawn node command and then monitor for the required string to start my tests ?
Based on previous question here where starting test on polling when Http://localhost:8000 is up and running.
Solution I am looking for is Starting test based on stdout data string matches - "Starting development server".
Yes, use spawn and look for the string, then run your tests, monitor SIGTERM and SIGINT, then pass it along to the child.
const {
spawn
} = require('child_process')
// your cmd to start the server, possibly spawn('python', ['manage.py', 'startserver'])
const server = spawn('node', ['server.js'])
let timer = null
server.stdout.on('data', (data) => {
console.log(`stdout: ${data}`)
// look for the string in stdout
if (data.includes('Starting development server')) {
console.log('Commencing tests in 2 seconds')
timer = setTimeout(() => {
console.log('Run tests')
// ...
// tests complete
setTimeout(() => {
console.log('Tests completed, shutting down server')
server.kill('SIGINT')
}, 2000)
}, 2000)
}
})
server.stderr.on('data', (data) => {
clearTimeout(timer)
console.error(`stderr: ${data}`)
});
server.on('close', (code) => {
clearTimeout(timer)
console.log(`child process exited with code ${code}`);
});
process
.on('SIGTERM', shutdown('SIGTERM'))
.on('SIGINT', shutdown('SIGINT'))
.on('uncaughtException', shutdown('uncaughtException'))
function shutdown(signal) {
return (err) => {
console.log(`\n${signal} signal received.`)
if (err && err !== signal) console.error(err.stack || err)
console.log('Killing child process.')
server.kill(signal)
}
}
Result
node spawn.js
stdout: Starting development server http://localhost:8000
Commencing tests in 2 seconds
Run tests
Tests completed, shutting down server
stdout:
SIGINT signal received.
stdout: Closing HTTP server.
stdout: HTTP server closed.
child process exited with code 0
The test server script used was the following, note above that it's passing back the SIGINT signal it received.
const express = require('express')
const app = express()
const port = 8000
app.get('/', (req, res) => res.send('Hello World!'))
const server = app.listen(port, () => console.log(`Starting development server http://localhost:${port}`))
process
.on('SIGTERM', shutdown('SIGTERM'))
.on('SIGINT', shutdown('SIGINT'))
.on('uncaughtException', shutdown('uncaughtException'))
function shutdown(signal) {
return (err) => {
console.log(`\n${signal} signal received.`)
if (err && err !== signal) console.error(err.stack || err)
console.log('Closing HTTP server.')
server.close(() => {
console.log('HTTP server closed.')
//
process.exit(err && err !== signal ? 1 : 0)
})
}
}

executing command from child_process.exec and cmd

In my Node.js program, I would like to know if a specific port is used so I execute the command below with child_process.exec (example with port 3001) :
netstat -na | find "3001"
If the port is used I get informations about the port as expected but If it is not used I get the following error:
I don't understand why I get this error because when I run the same command in cmd, If the port is not used it doesn't throw error:
Can anyone please tell me what's wrong ?
Node version: v10.16.0
I think you should try this. I have created API you can directly call.
This will return the result data.
const { exec } = require("child_process");
function os_func() {
this.execCommand = function(cmd, callback) {
exec(cmd, (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
callback(stdout);
});
}
}
app.get("/", (req, res) => {
console.log("inside get");
var os = new os_func();
os.execCommand('netstat -na | find "3001"', function (returnvalue) {
res.end(returnvalue)
});
});

Child process function not being triggered with no errors

I'm working on a Node.js app utilizing Electron. I need to access a executable in a certain directory and determine its output. The executable is a simple console application. I read the docs on Child Process and tried to use execFile. However, the callback function doesn't seem to execute.
Here's my code at the moment:
var exec = require('child_process').execFile
exec('E:/SteamLibrary/steamapps/common/GarrysMod/bin/gmad.exe', [], function(err, data) {
console.log(err);
console.log(data);
});
How could I go about fixing this?
Youre using windows so execFile() wouldnt work. It stated on docs.. for convenient I use docs example here with litle change.
const { spawn } = require('child_process');
const bat = spawn('C/steam/steam.exe');
bat.stdout.on('data', (data) => {
console.log(data.toString());
});
bat.stderr.on('data', (data) => {
console.log(data.toString());
});
bat.on('exit', (code) => {
console.log(`Child exited with code ${code}`);
});

How to prevent nodejs console close

Is there any alternative to PHP error_reporting(0) in nodejs? I want to prevent app from closing after an error, I tried the try and catch method, but it doesn't work.
So, how can I prevent node.js server from closing after an error ?
Edit:
There is an event for uncaught errors:
process.on('uncaughtException', function (err) {
console.log('Caught exception: ' + err);
});
See duplicate: Make node.js not exit on error
You could also use pm2 to run your script, pm2 will automatically restart your script on crash.
You need to catch the error.
For example
try {
error();
} catch(err) {
// do nothing
}
There is no other way as far as i know. So you could fix or catch these errors only.
After i review source code of node, I found there is a beautiful method to implement "ctrl+c" existing.
Create file block.js, content is:
const readline = require('readline')
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
})
const block = (data) => {
process.on('uncaughtException', function (err) {
console.log('Caught exception: ' + err)
})
rl.on('SIGINT', () => {
console.log(data)
rl.pause()
})
}
module.exports = {
block
}
Then require this js file in whatever main js file, and run this:
const { block } = require('./block.js')
block('Your exiting message!')
// your other js code after here
// ...
The block.js file would catch err and "ctrl+c" SIGINT exit.

Resources