简体   繁体   中英

Node.js: Easiest way to capture stdout into string variable

I have the following code:

const spawn = require("child_process").spawn;

const netStat = spawn('netstat', ['-nat']);
const grepPort = spawn('grep', ['3000']);
const grepStatus = spawn('grep', ['ESTABLISHED']);

console.log('Determining public ip\'s connected to port 3000');

// get port 3000 from netstat
netStat.stdout.on('data', (data) => {
  grepPort.stdin.write(data);
  });

netStat.on('close', (code) => {
  if (code !== 0) {console.log(`netstat process exited with code ${code}`);}
  grepPort.stdin.end();
});

// get ESTABLISHED from port 3000
grepPort.stdout.on('data', (data) => {
  grepStatus.stdin.write(data);
  });

grepPort.on('close', (code) => {
  grepStatus.stdin.end();
});

grepStatus.stdout.on('data', (data) => {
  console.log(data.toString())
  // Store data.toString() to variable here
});

I am trying to capture the final data into a string where the comment is in the 3rd to last line.

I've looked into streams, buffer objects, etc and got nothing to work (maybe I was doing them wrong?) so I'm looking for a fresh solution that will work or a simple "its not possible".

EDIT: Lets say the code is revised:

const spawn = require("child_process").spawn;
var port = 3000
console.log(`Determining public ip\'s connected to port ${port}`);

let output = '';

const proc = spawn('sh', [
  '-c',
  `netstat -nat | grep ${port}.*ESTABLISHED | awk '{print $5}' | grep -v .*${port}`
]);

proc.stdout.on('data', (chunk) => {
  output += chunk.toString();
});

proc.stderr.on('data', (chunk) => {
  console.log(chunk.toString());
});

proc.on('error', (err) => {
  console.error(err);
});

proc.on('exit', (code) => {
  console.log("Done");
});

console.log(output); // Should print output, no?

Thanks in advance for the help!

You can append all data event chunks onto one single string and do something with it when the pipe ends like so:

const spawn = require('child_process').spawn;
const proc = spawn('netstat', ['-nat']);

let output = '';
proc.stdout.on('data', (chunk) => {
  output += chunk.toString();
});
proc.on('exit', () => {
  console.log(output);
});

output starts as an empty string and each time there is a data event (more than once, usually) you can append the data to that string until the whole process is exit ed. Once the process exit s, you will have the total stdout output.

Also for your script, it might be easier to use one single spawn call and the sh command to connect all of those together with unix pipes outside of node.js. That, combined with the above would look like this:

const spawn = require("child_process").spawn;

console.log('Determining public ip\'s connected to port 3000');

let output = '';

const proc = spawn('sh', [
  '-c',
  'netstat -nat | grep 3000 | grep ESTABLISHED'
]);

proc.stdout.on('data', (chunk) => {
  output += chunk.toString();
});

proc.stderr.on('data', (chunk) => {
  console.log(chunk.toString());
});

proc.on('error', (err) => {
  console.error(err);
});

proc.on('exit', (code) => {
  console.log(code);
  console.log(output);
});

And if you still want separate spawn s, it may be easier/helpful to use the built-in .pipe methods to connect them together:

const spawn = require("child_process").spawn;

console.log('Determining public ip\'s connected to port 3000');

let output = '';

const netStat = spawn('netstat', ['-nat']);
const grepPort = spawn('grep', ['3000']);
netStat.stdout.pipe(grepPort.stdin);
const grepStatus = spawn('grep', ['ESTABLISHED']);
grepPort.stdout.pipe(grepStatus.stdin);

grepPort.stdout.on('data', (chunk) => {
  output += chunk.toString();
});

netstat.stderr.on('data', (chunk) => {
  console.log(chunk.toString());
});

grepPort.on('error', (err) => {
  console.error(err);
});

grepPort.on('exit', (code) => {
  console.log(code);
  console.log(output);
});

I found this error-prone locally because the process may exit before the pipes can be connected (eg grep likes to be informed it should listen to stdin with something like grep -f - otherwise it exits with status code 1). Additionally, each pipe can have stderr data events that you should listen to. That's a to handle so all pipes together might be helpful.

The grep line could be simpler too if it worked on your system, grep '3000.*ESTABLISHED' instead of two grep invocations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM