I spawn some command synchronously and want two things:
I’ve written this code:
var spawnSync = require('child_process').spawnSync;
var result = spawnSync('ls', [ '-l', '-a' ]);
var savedOutput = result.stdout;
console.log(String(savedOutput));
So, I store stdout in savedOutput variable — it’s ok, and log it out. But I haven’t pipe it to stdout. If the spawned process is long and write strings one by one, I see empty screen a long time, and at the end I see whole stdout of process.
I’ve add options for piping:
var spawnSync = require('child_process').spawnSync;
var result = spawnSync('ls', [ '-l', '-a' ], {
stdio: [ 'ignore', 1, 2 ]
});
var savedOutput = result.stdout;
console.log(String(savedOutput));
Stdout of spawned process is piped to stdout — it’s ok. But result.stdout is empty.
I’ve tried to use stream:
var spawnSync = require('child_process').spawnSync;
var stream = require('stream');
var grabber = new stream.Writable();
grabber._write = function(chunk, enc, done) {
console.log('Chunk:');
console.log(String(chunk));
done();
};
var result = spawnSync('ls', [ '-l', '-a' ], {
stdio: [ 'ignore', grabber, 2 ]
});
... but get an error:
internal/child_process.js:795
throw new TypeError('Incorrect value for stdio stream: ' +
^
TypeError: Incorrect value for stdio stream: Writable
If I set grabber.fd = 2
, I don’t get an error, but child stdout pipes to stdout instead of grabber.
So. How to save child stdout into variable and pipe it to stdout in the same time?
The node:child_process module provides the ability to spawn subprocesses in a manner that is similar, but not identical, to popen(3) . This capability is primarily provided by the child_process. spawn() function: const { spawn } = require('node:child_process'); const ls = spawn('ls', ['-lh', '/usr']); ls. stdout.
Spawn is useful when you want to make a continuous data transfer in binary/encoding format — e.g. transferring a 1 Gigabyte video, image, or log file. Fork is useful when you want to send individual messages — e.g. JSON or XML data messages.
I think the problem is that "spawnSync" is synchronous, and does not return control to node until the child process has exited. This means node does no processing during the execution of the child, and thus cannot see any of the intermediate output from the child.
You need to use the non-"sync" spawn. This will have additional complications in that your code is async, and you need to wait for the 'close' event to be sure the child data is collected. And you need to figure out what to do with stderr. Something like this:
const spawn = require('child_process').spawn;
const lsChild = spawn('ls', [ '-l', '-a' ]);
let savedOutput = '';
lsChild.stdout.on('data', data => {
const strData = data.toString();
console.log(strData);
savedOutput += strData;
});
lsChild.stderr.on('data', data => {
assert(false, 'Not sure what you want with stderr');
});
lsChild.on('close', code => {
console.log('Child exited with', code, 'and stdout has been saved');
// at this point 'savedOutput' contains all your data.
});
Does this solve your problem?
var spawnSync = require('child_process').spawnSync;
var result = spawnSync('ls', [ '-l', '-a' ], {
cwd: process.cwd(),
env: process.env,
stdio: 'pipe',
encoding: 'utf-8'
});
var savedOutput = result.stdout;
console.log(String(savedOutput));
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