Node.js:将标准输出捕获到字符串变量中的最简单方法

标签 node.js stream console global-variables stdout

我有以下代码:

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
});

我试图将最终数据捕获到一个字符串中,其中注释位于倒数第三行。

我研究了流、缓冲区对象等,但没有任何效果(也许我做错了?)所以我正在寻找一个可行的新解决方案或一个简单的“它不可能”。

编辑: 假设代码已修改:

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?

预先感谢您的帮助!

最佳答案

您可以将所有数据事件 block 附加到一个字符串上,并在管道结束时对其执行某些操作,如下所示:

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 以空字符串开始,每次出现 data 事件(通常不止一次)时,您都可以将数据附加到该字符串,直到整个过程退出。一旦进程退出,您将获得总的stdout输出。

对于您的脚本来说,使用一个 spawn 调用和 sh 命令将所有这些与 Node.js 外部的 unix 管道连接起来可能会更容易。结合上面的内容看起来像这样:

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);
});

如果您仍然想要单独的 spawn,使用内置的 .pipe 方法将它们连接在一起可能会更容易/更有帮助:

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);
});

我在本地发现这个容易出错,因为进程可能会在连接管道之前退出(例如,grep 喜欢被告知它应该使用 grep -f - 之类的东西监听 stdin,否则它会以状态代码 1 退出)。此外,每个管道都可以有您应该监听的 stderr data 事件。这是一个需要处理的问题,因此将所有管道放在一起可能会有所帮助。

如果 grep 行在您的系统上运行的话,它也可以更简单,grep '3000.*ESTABLISHED' 而不是两次 grep 调用。

关于Node.js:将标准输出捕获到字符串变量中的最简单方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52864241/

相关文章:

c++ - 如何删除也是函数返回值的新分配的 char?

assembly 控制台暂停

java - 在 Java 中打印字符串变量

node.js - Nodejs 的依赖管理不仅控制模块的版本,还控制 npm 和 Node 本身的版本

javascript - 入门 : Setup Database for Node. js

javascript - Promisify Redis 客户端

javascript - 管道订购很重要吗?将 stdin 通过管道传输到 http 请求并将结果通过管道传输到 stdout

ios - 无法写入使用 CFStreamCreatePairWithSocket 成功创建的 CFWriteStream

Javascript Electron 从列表中删除/忽略某个项目

javascript - 包装 Firebug(或类似)控制台 api 时如何访问行号