4

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.

Alexander Mills
  • 90,741
  • 139
  • 482
  • 817
  • http://stackoverflow.com/questions/10213501/communicating-between-two-different-processes-in-node-js - is it your case? – Andrey Dec 08 '16 at 07:18
  • no, those are two node.js processes. I am talking about a node.js process and an sh/bash process. I don't know how to make IPC calls in bash. – Alexander Mills Dec 08 '16 at 07:21
  • I doubt you will want to be using node's IPC mechanism if the child process is not a node process. Otherwise you will have to implement node's IPC JSON protocol in bash and that protocol is not really a public thing so it could change. – mscdex Dec 08 '16 at 07:34
  • yeah, but will I really "have" to implement node.js IPC JSON, would sending any old string/buffer work? – Alexander Mills Dec 08 '16 at 07:35
  • Check out this issue: https://github.com/nodejs/help/issues/48 – Craig Dec 08 '16 at 07:48

1 Answers1

6

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.

Alexander Mills
  • 90,741
  • 139
  • 482
  • 817
Craig
  • 1,065
  • 3
  • 12
  • 26
  • One thing I am confused about is, how does a bash script wait for a message to be received from the parent? In other words, will the read -u command wait for the next message or will it just return empty if there is no message? – Alexander Mills Dec 08 '16 at 18:03
  • In .js it's pretty clear how to do this, you register a callback and any subsequent messages will be received, but thats not really how bash works TMK – Alexander Mills Dec 08 '16 at 18:04
  • And for that matter, most languages don't work that way; most languages need that evented behavior and essentially a callback; I can implement such a callback in most languages, but bash in particular is confusing as far as how to implement that – Alexander Mills Dec 08 '16 at 18:06
  • I am going to look at the node source, but if you happen to know what kind of IPC channel is used that would help..e.g. pipes, semaphore, reference to same file somewhere, idk – Alexander Mills Dec 08 '16 at 18:44
  • although WRT to read -u, on Ubuntu 16.04, I got "read: Illegal option -u" – Alexander Mills Dec 09 '16 at 03:02