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.
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.
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}`);
});
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.
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}`);
});
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}`);
});
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?
Figured it out: I could push a readable stream to the child.
...
const stream = require('stream');
...
var stdinStream = new stream.Readable();
stdinStream.push('hello\n'); // Add data to the internal queue for users of the stream to consume
stdinStream.pipe(child.stdin);
Thanks to this answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With