user8076620
user8076620

Reputation:

run a few node.js web servers from within a node.js application

I would like to control a few web sites using a UI to start and stop them, changing the ports that the different web server's listen to.

PM2 is a command line utility to manage node sites, but does not have a user interface that I can supply my customer.

How can I run a node.js web site from within another node.js web application.

The following node.js code does not seem to do the work.

const { exec } = require('child_process');

....

exec('node app.js', (err, stdout, stderr) => {
    if (err) {
        console.log(`err: ${err}`);
        return;
    }

    // the *entire* stdout and stderr (buffered)
    console.log(`stdout: ${stdout}`);
    console.log(`stderr: ${stderr}`);
});

note: regular linux commands instead of the 'node app.js' command work as expected.

Upvotes: 2

Views: 562

Answers (2)

brickpop
brickpop

Reputation: 2796

The simplest alternative would be to keep a collection of ExpressJS instances and create/destroy them as needed within NodeJS:

const express = require("express");

var app1 = express();
app1.use("/", function(req, res){ res.send("APP 1"); });

var app2 = express();
app2.use("/", function(req, res){ res.send("APP 2"); });

// start them
var server1 = app.listen(9001);
var server2 = app.listen(9002);

// close the first one
server1.close();

// port 9001 is closed
// port 9002 is still listening

However, if you need to spawn independent processess, you could have:

const { spawn } = require("child_process");

// Prevent Ctrl+C from killing the parent process before the children exit
process.on("SIGINT", () => {
  console.log("Terminating the process...");
  if (runningProcesses > 0) {
    setTimeout(() => process.exit(), 3000);
  } else {
    process.exit();
  }
});

function asyncSpawn(command, parameters = []) {
  return new Promise((resolve, reject) => {
    runningProcesses++;
    console.log(command, ...parameters, "\n");

    spawn(command, parameters, {
      stdio: "inherit"
    })
      .on("close", code => {
        if (code)
          reject(new Error(command + " process exited with code " + code));
        else resolve();
      })
      .on("exit", error => {
        runningProcesses--;
        if (error) reject(error);
        else resolve();
      });
  });
}

And launch new processes like this:

asyncSpawn("node", ["server.js", "--param1"])
    .then(() => console.log("DONE"))
    .catch(err => console.error(err));

Upvotes: 1

user8076620
user8076620

Reputation:

Got the following code to work in case you want to run the same: This is the code on the server that will spawn a new web server.

app.get('/start', ( req, res ) => {

    var node = spawn('node', ['app.js &'], { shell: true });

    node.stdout.on('data', function (data) {
      console.log('stdout: ' + data.toString());
    });

    node.stderr.on('data', function (data) {
      console.log('stderr: ' + data.toString());
    });

    node.on('exit', function (code) {
      console.log('child process exited with code ' + 
        code.toString());
    });

    // Notify client 
   res.status(200).send( {} );
});

Upvotes: 2

Related Questions