1

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.

Jeeva
  • 1,550
  • 12
  • 15
  • Can you provide a bit more detail about why you want to do this? It seems rather unorthodox. See also [What is the X Y problem?](https://meta.stackexchange.com/a/66378/102937) – Robert Harvey Jan 18 '19 at 15:24
  • Also, you can't `await` a function that will return a result into a callback (well, you can, but it wouldn't work as you expects) – RidgeA Jan 18 '19 at 15:30
  • which version of node do you are using? – Manuel Spigolon Jan 18 '19 at 15:32
  • @Manuel Spigolon, node - 8.10.0, npm - 5.6.0 – Jeeva Jan 18 '19 at 15:33
  • @RobertHarvey, I'm trying to develop a cryptocurrency wallet application, in which i need to simulate a separate instance for each user for demo purpose. – Jeeva Jan 18 '19 at 15:35
  • @RidgeA, yes you are right, i have removed it so. – Jeeva Jan 18 '19 at 15:36
  • `stdout` may provide more pertinent information than `err` will. I'd suggest looking into the values of `stdout` when the command both succeeds and fails and key off that – Zenkylo Jan 18 '19 at 15:36
  • @Zenkylo, correct but it had never returned anything either error or success result. But in the background, when i tried to run the port 5000, It runs. If the second application ran means then it might have returned something, In my case it doesn't – Jeeva Jan 18 '19 at 15:41
  • 1
    The callback function is only called once the process terminates. If your child process remains running the callback is not triggered. – kvnam Jan 18 '19 at 15:42
  • @KVNam yes, callback Called with the output when process terminates. If thats the case i cannot run my server instance independently. if i terminate it, then it will stop the second application's server instance which is not right as per my task. – Jeeva Jan 18 '19 at 15:50
  • @Jeeva Yes. I'm not sure what your exact case is, but you will need to find a way to trigger process termination based on some condition, in order to access the result. – kvnam Jan 18 '19 at 15:54
  • Thank you for the useful comments @KVNam, i will go through the nodejs child processes document again. – Jeeva Jan 18 '19 at 15:57
  • @Jeeva Glad I could help, I've added the answer below with a link to the child process documentation. Would appreciate it if you could mark it as the answer. – kvnam Jan 18 '19 at 16:00
  • What if we process a bash script that runs the second node instance. For example, `exec('./someBashScript', (err, stdout, stderr) {...}` The bash script would run the second instance, for example; `#!/usr/bin/bash node/users/user1/demoProjects/demo1.js` – Zenkylo Jan 18 '19 at 16:15

2 Answers2

2

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
        });
    }
});
hurricane
  • 6,521
  • 2
  • 34
  • 44
  • How is this working for you? I thought `stdout` and `stderr` are of either string or buffer type, containing the output from the child process and not in fact pipes. I'm getting an error when I try this. – kvnam Jan 18 '19 at 15:51
  • @hurricane, Thank you for your answer, Now I can able to see the data events – Jeeva Jan 19 '19 at 05:32
1

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

kvnam
  • 1,285
  • 2
  • 19
  • 34
  • Hi KVNam, I have tried the below scenario. The callback is called once the process terminates. eg. replaced the **let startServerInstance = 'cd "/users/user1/demoProjects/demo1" && npm run dev';** with **let startServerInstance = 'mkdir -p ./testDir'**. It had created the folder. Hence the process is completed and i got the response. But in my case, its an ever running process. so i manually killed the port after it ran. By this time it might have fired the callback so the process is complete by killing it, but i didnt get any response – Jeeva Jan 18 '19 at 16:33
  • 1
    The corrected answer given by @hurricane below is the right way to capture stdout data from a running process. The `child` variable which holds the ChildProcess instance, can be used to watch for `data` events. This is outside the callback so you don't have to wait for the process to terminate. There is a `message` event as well which you can check out. – kvnam Jan 18 '19 at 17:56