我有以下代码:
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?
预先感谢您的帮助!
您可以将所有数据事件块附加到一个字符串上,并在管道结束时对其执行某些操作,如下所示:
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
事件(通常不止一次),您都可以将数据附加到该字符串,直到整个过程完成 exit
。一旦过程exit
,您将获得总的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
喜欢被告知它应该用stdin
之类的东西监听grep -f -
,否则它会以状态代码1退出)。此外,每个管道都可以有您应该监听的 stderr
data
事件。这是一个需要处理的问题,因此将所有管道放在一起可能会有所帮助。
grep 行 也可以 更简单(如果它适用于您的系统),
grep '3000.*ESTABLISHED'
而不是两次 grep 调用。
我建议使用 exec 作为承诺。
const exec = require('util').promisify(require('child_process').exec);
const { stdout, stderr } = await exec('Write your command here');
console.log(stdout, stderr);