我仍在努力掌握如何运行linux或windows shell命令并在 node 内捕获输出的细节.js;最终,我想做这样的事情...

//pseudocode
output = run_command(cmd, args)

重要的一点是,output必须可用于全局范围的变量(或对象).我try 了以下功能,但由于某种原因,我得到undefined打印到控制台...

function run_cmd(cmd, args, cb) {
  var spawn = require('child_process').spawn
  var child = spawn(cmd, args);
  var me = this;
  child.stdout.on('data', function(me, data) {
    cb(me, data);
  });
}
foo = new run_cmd('dir', ['/B'], function (me, data){me.stdout=data;});
console.log(foo.stdout);  // yields "undefined" <------

我很难理解上面的代码在哪里中断...该模型的一个非常简单的原型可以工作...

function try_this(cmd, cb) {
  var me = this;
  cb(me, cmd)
}
bar = new try_this('guacamole', function (me, cmd){me.output=cmd;})
console.log(bar.output); // yields "guacamole" <----

有人能帮我理解为什么try_this()有效,而run_cmd()无效吗?FWIW,我需要使用child_process.spawn,因为child_process.exec有200KB的缓冲限制.

最终决议

我接受詹姆斯·怀特的答案,但这正是对我有效的代码...

function cmd_exec(cmd, args, cb_stdout, cb_end) {
  var spawn = require('child_process').spawn,
    child = spawn(cmd, args),
    me = this;
  me.exit = 0;  // Send a cb to set 1 when cmd exits
  me.stdout = "";
  child.stdout.on('data', function (data) { cb_stdout(me, data) });
  child.stdout.on('end', function () { cb_end(me) });
}
foo = new cmd_exec('netstat', ['-rn'], 
  function (me, data) {me.stdout += data.toString();},
  function (me) {me.exit = 1;}
);
function log_console() {
  console.log(foo.stdout);
}
setTimeout(
  // wait 0.25 seconds and print the output
  log_console,
250);

推荐答案

这里有三个问题需要解决:

First是指在异步使用stdout时需要同步行为.run_cmd函数中的所有调用都是异步的,因此它将生成子进程并立即返回,而不管是否从stdout读取了部分、全部或任何数据.因此,当你 run 时

console.log(foo.stdout);

你会得到存储在foo中的任何东西.目前还不能保证会发生什么,因为您的子进程可能仍在运行.

Second表示stdout是readable stream,因此1)数据事件可以被多次调用,2)回调是一个缓冲区,而不是字符串.易于补救;换衣服

foo = new run_cmd(
    'netstat.exe', ['-an'], function (me, data){me.stdout=data;}
);

进入

foo = new run_cmd(
    'netstat.exe', ['-an'], function (me, buffer){me.stdout+=buffer.toString();}
);

so that we convert our buffer 进入 a string and append that string to our stdout variable.

Third表示只有当您收到"end"事件时,才能知道您已收到所有输出,这意味着我们需要另一个侦听器和回调:

function run_cmd(cmd, args, cb, end) {
    // ...
    child.stdout.on('end', end);
}

所以,你的最终结果是:

function run_cmd(cmd, args, cb, end) {
    var spawn = require('child_process').spawn,
        child = spawn(cmd, args),
        me = this;
    child.stdout.on('data', function (buffer) { cb(me, buffer) });
    child.stdout.on('end', end);
}

// Run C:\Windows\System32\netstat.exe -an
var foo = new run_cmd(
    'netstat.exe', ['-an'],
    function (me, buffer) { me.stdout += buffer.toString() },
    function () { console.log(foo.stdout) }
);

Node.js相关问答推荐

如何修复PayPal Node.js Webhook中Webhook签名验证失败?''

MongoDB:更新批量操作中许多不能正常工作的内容

创建查询以展开数组并筛选出具有特定值的元素之后的元素

try 插入重复的邮箱时,mongoDB DuplicateKey 错误未定义

使用单个 MongoDB 查询更新多个元素

如何使用包含条件正确分页的 sequelize 查询?

错误:0308010C:try 通过 Github 推送部署到 firebase 托管时出现数字

Node.js 上的 CLI 应用程序如何通过 child_process 将选项值作为参数传递给 Shell 命令

无服务器部署使用无服务器组合抛出`spawn serverless ENOENT`

如何使用 Jest 模拟异步函数的延迟时间

为什么我的 Heroku Express API 数据是持久的,即使它只是来自一个变量

如何使用 Puppeteer 从输入中删除现有文本?

npm 不会安装 express 吗?

Node.js、Cygwin 和 Socket.io 走进一家wine 吧……Node.js 抛出 ENOBUFS,所有人都死了

Node_redis - 如何删除密钥?

判断一个数组中的每个元素是否都在第二个数组中

Nodejs将字符串转换为UTF-8

使用 gzip/deflate 压缩的简单 HTTP 请求

Puppeteer 等待所有图像加载然后截图

Mongoose - 验证邮箱语法