I need to capture in a custom stream outputs of a spawned child process.
child_process.spawn(command[, args][, options])
For example,
var s = fs.createWriteStream('/tmp/test.txt');
child_process.spawn('ifconfig', [], {stdio: [null, s, null]})
Now how do I read from the /tmp/test.txt
in real time?
It looks like child_process.spawn
is not using stream.Writable.prototype.write
nor stream.Writable.prototype._write
for its execution.
For example,
s.write = function() { console.log("this will never get printed"); };
As well as,
s.__proto__._write = function() { console.log("this will never get printed"); };
It looks like it uses file descriptors under-the-hood to write from child_process.spawn
to a file.
Doing this does not work:
var s2 = fs.createReadStream('/tmp/test.txt');
s2.on("data", function() { console.log("this will never get printed either"); });
So, how can I get the STDOUT
contents of a child process?
What I want to achieve is to stream STDOUT
of a child process to a socket. If I provide the socket directly to the child_process.spawn
as a stdio
parameter it closes the socket when it finishes, but I want to keep it open.
Update:
The solution is to use default {stdio: ['pipe', 'pipe', 'pipe']}
options and listen to the created .stdout
of the child process.
var cmd = child_process.spaw('ifconfig');
cmd.stdout.on("data", (data) => { ... });
Now, to up the ante, a more challenging question:
-- How do you read the STDOUT
of the child process and still preserve the colors?
For example, if you send STDOUT
to process.stdout
like so:
child_process.spawn('ifconfig', [], {stdio: [null, process.stdout, null]});
it will keep the colors and print colored output to the console, because the .isTTY
property is set to true
on process.stdout
.
process.stdout.isTTY // true
Now if you use the default {stdio: ['pipe', 'pipe', 'pipe']}
, the data you will read will be stripped of console colors. How do you get the colors?
One way to do that would be creating your own custom stream with fs.createWriteStream
, because child_process.spawn
requires your streams to have a file descriptor.
Then setting .isTTY
of that stream to true
, to preserve colors.
And finally you would need to capture the data what child_process.spawn
writes to that stream, but since child_process.spawn
does not use .prototype.write
nor .prototype._write
of the stream, you would need to capture its contents in some other hacky way.
That's probably why child_process.spawn
requires your stream to have a file descriptor because it bypasses the .prototype.write
call and writes directly to the file under-the-hood.
Any ideas how to implement this?
I need to capture in a custom stream outputs of a spawned child process.
child_process.spawn(command[, args][, options])
For example,
var s = fs.createWriteStream('/tmp/test.txt');
child_process.spawn('ifconfig', [], {stdio: [null, s, null]})
Now how do I read from the /tmp/test.txt
in real time?
It looks like child_process.spawn
is not using stream.Writable.prototype.write
nor stream.Writable.prototype._write
for its execution.
For example,
s.write = function() { console.log("this will never get printed"); };
As well as,
s.__proto__._write = function() { console.log("this will never get printed"); };
It looks like it uses file descriptors under-the-hood to write from child_process.spawn
to a file.
Doing this does not work:
var s2 = fs.createReadStream('/tmp/test.txt');
s2.on("data", function() { console.log("this will never get printed either"); });
So, how can I get the STDOUT
contents of a child process?
What I want to achieve is to stream STDOUT
of a child process to a socket. If I provide the socket directly to the child_process.spawn
as a stdio
parameter it closes the socket when it finishes, but I want to keep it open.
Update:
The solution is to use default {stdio: ['pipe', 'pipe', 'pipe']}
options and listen to the created .stdout
of the child process.
var cmd = child_process.spaw('ifconfig');
cmd.stdout.on("data", (data) => { ... });
Now, to up the ante, a more challenging question:
-- How do you read the STDOUT
of the child process and still preserve the colors?
For example, if you send STDOUT
to process.stdout
like so:
child_process.spawn('ifconfig', [], {stdio: [null, process.stdout, null]});
it will keep the colors and print colored output to the console, because the .isTTY
property is set to true
on process.stdout
.
process.stdout.isTTY // true
Now if you use the default {stdio: ['pipe', 'pipe', 'pipe']}
, the data you will read will be stripped of console colors. How do you get the colors?
One way to do that would be creating your own custom stream with fs.createWriteStream
, because child_process.spawn
requires your streams to have a file descriptor.
Then setting .isTTY
of that stream to true
, to preserve colors.
And finally you would need to capture the data what child_process.spawn
writes to that stream, but since child_process.spawn
does not use .prototype.write
nor .prototype._write
of the stream, you would need to capture its contents in some other hacky way.
That's probably why child_process.spawn
requires your stream to have a file descriptor because it bypasses the .prototype.write
call and writes directly to the file under-the-hood.
Any ideas how to implement this?
Share Improve this question edited Jun 3, 2015 at 11:33 Vad asked Jun 3, 2015 at 9:56 VadVad 4,0993 gold badges31 silver badges35 bronze badges3 Answers
Reset to default 8You can do it without using a temporary file:
var process = child_process.spawn(command[, args][, options]);
process.stdout.on('data', function (chunk) {
console.log(chunk);
});
Hi I'm on my phone but I will try to guide you as I can. I will clarify when near a computer if needed
What I think you want is to read the stdout
from a spawn and do something with the data?
You can give the spawn a variable name instead of just running the function, e.g:
var child = spawn();
Then listen to the output like:
child.stdout.on('data', function(data) {
console.log(data.toString());
});
You could use that to write the data then to a file or whatever you may want to do with it.
The stdio
option requires file descriptors, not stream objects, so one way to do it is use use fs.openSync()
to create an output file descriptor and us that.
Taking your first example, but using fs.openSync()
:
var s = fs.openSync('/tmp/test.txt', 'w');
var p = child_process.spawn('ifconfig', [], {stdio: [process.stdin, s, process.stderr]});
You could also set both stdout and stderr to the same file descriptor (for the same effect as bash's 2>&1
).
You'll need to close the file when you are done, so:
p.on('close', function(code) {
fs.closeSync(s);
// do something useful with the exit code ...
});