Requirements
I try to send custom messages to the stdin of a persistent child process. The child is not a node process, but an arbitrary program. The child process uses a REPL interactive prompt to accept user input and print result to stdout, which gets piped back to the parent process. I need to be able to keep sending messages to the child and get results consistently.
I know that we can send messages to NodeJS-based child processes using fork()
, but that doesn't work with non-node processes.
Attempt 1: Pipe parent stdin to child stdin
My initial attempt is to allow user to enter message from parent process' stdin, and pipe it through its child process. This works but not quite what I want in the end.
Here is the parent process: hello_childstdin.js
const {join} = require('path');
const {spawn} = require('child_process');
const child = spawn('/usr/local/bin/python3', [join(__dirname, 'hello_childstdin.py')]);
process.stdin.pipe(child.stdin);
child.stdout.on('data', (data) => {
console.log(`child stdout: \n${data}`);
});
child.stderr.on('data', (data) => {
console.log(`child stderr: \n${data}`);
});
Here is the child process: hello_childstdin.py
while True:
cmd = input('Enter command here (hello, bye, do it):')
print('cmd: {}'.format(cmd))
msg = cmd+': done\n' if cmd in ('hello', 'bye', 'do it') else 'undefined cmd: {}'.format(cmd)
with open('/path/to/hello_childstdin.txt', 'a') as f:
f.write(msg)
print('msg: {}'.format(msg))
However, What I really want is to send messages directly to child process's stdin without human intervention?
I've tried the following but failed.
Attempt 2: Pipe then write to parent stdin.
the parent process: hello_childstdin.js
const {join} = require('path');
const {spawn} = require('child_process');
const child = spawn('/usr/local/bin/python3', [join(__dirname, 'hello_childstdin.py')]);
process.stdin.pipe(child.stdin);
// Trying to write to parent process stdin
process.stdin.write('hello\n');
child.stdout.on('data', (data) => {
console.log(`child stdout: \n${data}`);
});
child.stderr.on('data', (data) => {
console.log(`child stderr: \n${data}`);
});
Attempt 3: Write to child stdin.
the parent process: hello_childstdin.js
const {join} = require('path');
const {spawn} = require('child_process');
const child = spawn('/usr/local/bin/python3', [join(__dirname, 'hello_childstdin.py')]);
process.stdin.pipe(child.stdin);
// Trying to write to parent process stdin
child.stdin.write('hello\n');
child.stdout.on('data', (data) => {
console.log(`child stdout: \n${data}`);
});
child.stderr.on('data', (data) => {
console.log(`child stderr: \n${data}`);
});
Attempt 4
Seeing docs for child.stdin explain:
If the child is waiting to read all its input, it will not continue until this stream has been closed via end().
I then tried the following in my parent process.
// ... same as above ...
child.stdin.write('hello\n');
child.stdin.end();
// ... same as above ...
This ends child and does not write message over, either.
What would be the right way to duplex-communicate with a child process that's not forked?