Alexander Mills
Alexander Mills

Reputation: 100210

Send IPC message with sh/bash to parent process (Node.js)

I have a Node.js process and this process forks an sh child process to run a bash script. Something like this:

const cp = require('child_process');

const n = cp.spawn('sh',['foo.sh'], {
     stdio: ['ignore','ignore','ignore','ipc']
});

in my bash script (foo.sh), how can I send an IPC message back to the Node.js parent process? Cannot find out how to do that.

Doing some more research, looks like I will be getting closer to the IPC internals. One thing that might help is if I pass the parent PID to the bash script, then maybe I can do something with that.

Upvotes: 4

Views: 2479

Answers (1)

Craig
Craig

Reputation: 1085

When you add 'ipc' to your stdio options, the parent process and child process will establish a communication channel, and provide a file descriptor for the child process to use. This descriptor will be defined in your environment as $NODE_CHANNEL_FD. You can redirect output to this descriptor and it will be sent to the parent process to be parsed and handled.

As a simple example, I sent my name from the bash script to the parent process to be logged.

index.js

const cp = require('child_process');
const n = cp.spawn('sh', ['foo.sh'], {
    stdio: ['ignore', 'ignore', 'ignore', 'ipc']
});

n.on('message', (data) => {
    console.log('name: ' + data.name);
});

foo.sh

printf "{\"name\": \"Craig\"}\n" 1>&$NODE_CHANNEL_FD

Essentially what is happening in the bash file is:

  1. I'm using the printf command to send the JSON to stdout, file descriptor 1.
  2. And then redirecting it to a reference (&) of the $NODE_CHANNEL_FD

Note that the JSON you send must be properly formatted and terminated with a \n character

If you wanted to send data from the parent process to the bash process you could add

n.send({"message": "hello world"});

to your JavaScript, and in the bash file you could use something along the lines of

MESSAGE=read -u $NODE_CHANNEL_FD
echo " => message from parent process => $MESSAGE"

Note that you will have to change your stdio options so that you are not ignoring the standard output of the child process. You could set them to ['ignore', 1, 'ignore', 'ipc'] so that the child process' standard output goes straight to the parent's.

Upvotes: 6

Related Questions