子进程:stdout参数

伍德

根据文档,child_process.exec命令的回调stdout参数应为Buffer类型。

http://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback

问题在于它不是:

var exec, child;
exec = require('child_process').exec;

child = exec('/bin/echo -n "hello"', function (error, stdout, stderr) {
    if (error) {
        console.log("error!");
        return;
    }
    console.log("isBuffer: " + Buffer.isBuffer(stdout));
    console.log("type: " + typeof stdout);
});

此打印

isBuffer: false
type: string

为什么?这是文档错误吗?

这是一个主要问题,因为如果存在二进制数据stdout,我会得到不正确的数据。{encoding: 'binary'}进入选项并没有帮助。

洛朗·佩林

Node.js的源代码显示,截至0.10.18,由于输出始终是一个字符串。如果要获取二进制数据,则必须使用spawn

但是,如果您通过了,似乎node.js 0.12将引入一个选项来获取二进制数据{encoding: 'buffer'}

https://github.com/joyent/node/blob/master/lib/child_process.js#L617):

if (options.encoding !== 'buffer' && Buffer.isEncoding(options.encoding)) {

编辑:代码示例取自母版,尚不处于稳定版本。

编辑2:这是该版本的反向版本,该版本exec将接受缓冲区编码:

var util = require('util'),
    spawn = require('child_process').spawn;

var exec = function(command /*, options, callback */) {
  var file, args, options, callback;

  if (typeof arguments[1] === 'function') {
    options = undefined;
    callback = arguments[1];
  } else {
    options = arguments[1];
    callback = arguments[2];
  }

  if (process.platform === 'win32') {
    file = 'cmd.exe';
    args = ['/s', '/c', '"' + command + '"'];
    // Make a shallow copy before patching so we don't clobber the user's
    // options object.
    options = util._extend({}, options);
    options.windowsVerbatimArguments = true;
  } else {
    file = '/bin/sh';
    args = ['-c', command];
  }

  if (options && options.shell)
    file = options.shell;

  return execFile(file, args, options, callback);
};


var execFile = function(file /* args, options, callback */) {
  var args, callback;
  var options = {
    encoding: 'utf8',
    timeout: 0,
    maxBuffer: 200 * 1024,
    killSignal: 'SIGTERM',
    cwd: null,
    env: null
  };

  // Parse the parameters.

  if (typeof(arguments[arguments.length - 1]) === 'function') {
    callback = arguments[arguments.length - 1];
  }

  if (util.isArray(arguments[1])) {
    args = arguments[1];
    options = util._extend(options, arguments[2]);
  } else {
    args = [];
    options = util._extend(options, arguments[1]);
  }

  var child = spawn(file, args, {
    cwd: options.cwd,
    env: options.env,
    windowsVerbatimArguments: !!options.windowsVerbatimArguments
  });

  var encoding;
  var _stdout;
  var _stderr;
  if (options.encoding !== 'buffer' && Buffer.isEncoding(options.encoding)) {
    encoding = options.encoding;
    _stdout = '';
    _stderr = '';
  } else {
    _stdout = [];
    _stderr = [];
    encoding = null;
  }
  var stdoutLen = 0;
  var stderrLen = 0;
  var killed = false;
  var exited = false;
  var timeoutId;

  var ex;

  function exithandler(code, signal) {
    if (exited) return;
    exited = true;

    if (timeoutId) {
      clearTimeout(timeoutId);
      timeoutId = null;
    }

    if (!callback) return;

    // merge chunks
    var stdout;
    var stderr;
    if (!encoding) {
      stdout = Buffer.concat(_stdout);
      stderr = Buffer.concat(_stderr);
    } else {
      stdout = _stdout;
      stderr = _stderr;
    }

    if (ex) {
      callback(ex, stdout, stderr);
    } else if (code === 0 && signal === null) {
      callback(null, stdout, stderr);
    } else {
      ex = new Error('Command failed: ' + stderr);
      ex.killed = child.killed || killed;
      ex.code = code < 0 ? uv.errname(code) : code;
      ex.signal = signal;
      callback(ex, stdout, stderr);
    }
  }

  function errorhandler(e) {
    ex = e;
    child.stdout.destroy();
    child.stderr.destroy();
    exithandler();
  }

  function kill() {
    child.stdout.destroy();
    child.stderr.destroy();

    killed = true;
    try {
      child.kill(options.killSignal);
    } catch (e) {
      ex = e;
      exithandler();
    }
  }

  if (options.timeout > 0) {
    timeoutId = setTimeout(function() {
      kill();
      timeoutId = null;
    }, options.timeout);
  }

  child.stdout.addListener('data', function(chunk) {
    stdoutLen += chunk.length;

    if (stdoutLen > options.maxBuffer) {
      ex = new Error('stdout maxBuffer exceeded.');
      kill();
    } else {
      if (!encoding)
        _stdout.push(chunk);
      else
        _stdout += chunk;
    }
  });

  child.stderr.addListener('data', function(chunk) {
    stderrLen += chunk.length;

    if (stderrLen > options.maxBuffer) {
      ex = new Error('stderr maxBuffer exceeded.');
      kill();
    } else {
      if (!encoding)
        _stderr.push(chunk);
      else
        _stderr += chunk;
    }
  });

  if (encoding) {
    child.stderr.setEncoding(encoding);
    child.stdout.setEncoding(encoding);
  }

  child.addListener('close', exithandler);
  child.addListener('error', errorhandler);

  return child;
};

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

python子进程缺少参数

来自分类Dev

如何使用子进程和Popen从长时间运行的进程中返回stdout?

来自分类Dev

将子进程的stdout / stderr重定向到文件

来自分类Dev

在Python的子进程/ Popen中将stdout重定向到stderr

来自分类Dev

如果创建,Python子进程stderr / stdout字段为None

来自分类Dev

Python子进程Popen stdout仅用于变量

来自分类Dev

实时读取/写入子进程stdin / stdout

来自分类Dev

如何永远将子进程输出打印到stdout。

来自分类Dev

使用stdout / stderr以外的管道与子进程进行通信

来自分类Dev

除非子进程fllush(stdout),否则Node.js始终无法完全捕获子进程的stdout数据。

来自分类Dev

带参数的Windows子进程

来自分类Dev

如何在node.js子进程模块中将消息以及stdout从子进程传递到父进程?

来自分类Dev

将sys.stdout作为参数传递给进程

来自分类Dev

将stdout重定向到文件时,正向子进程stdout不起作用

来自分类Dev

如何使子进程按顺序获取stdout和stderr?

来自分类Dev

Perl捕获子进程的STDERR和STDOUT

来自分类Dev

子进程在stdout和os.devnull之间选择

来自分类Dev

C:无法从附加到子进程的stdout的管道读取

来自分类Dev

如何使用子进程popen清除“ cmd.exe”的STDOUT?

来自分类Dev

子进程:stdout和stderror似乎互换或混合

来自分类Dev

如何使用子进程和Popen从长时间运行的进程中返回stdout?

来自分类Dev

Python子进程Popen传递参数

来自分类Dev

在Python的子进程/ Popen中将stdout重定向到stderr

来自分类Dev

Python子进程Popen stdout仅用于变量

来自分类Dev

Python子进程没有正确的参数

来自分类Dev

Python子进程抑制stdout和stderr

来自分类Dev

带参数的Windows子进程

来自分类Dev

将stdout重定向到文件时,正向子进程stdout不起作用

来自分类Dev

带参数的 Python 子进程

Related 相关文章

  1. 1

    python子进程缺少参数

  2. 2

    如何使用子进程和Popen从长时间运行的进程中返回stdout?

  3. 3

    将子进程的stdout / stderr重定向到文件

  4. 4

    在Python的子进程/ Popen中将stdout重定向到stderr

  5. 5

    如果创建,Python子进程stderr / stdout字段为None

  6. 6

    Python子进程Popen stdout仅用于变量

  7. 7

    实时读取/写入子进程stdin / stdout

  8. 8

    如何永远将子进程输出打印到stdout。

  9. 9

    使用stdout / stderr以外的管道与子进程进行通信

  10. 10

    除非子进程fllush(stdout),否则Node.js始终无法完全捕获子进程的stdout数据。

  11. 11

    带参数的Windows子进程

  12. 12

    如何在node.js子进程模块中将消息以及stdout从子进程传递到父进程?

  13. 13

    将sys.stdout作为参数传递给进程

  14. 14

    将stdout重定向到文件时,正向子进程stdout不起作用

  15. 15

    如何使子进程按顺序获取stdout和stderr?

  16. 16

    Perl捕获子进程的STDERR和STDOUT

  17. 17

    子进程在stdout和os.devnull之间选择

  18. 18

    C:无法从附加到子进程的stdout的管道读取

  19. 19

    如何使用子进程popen清除“ cmd.exe”的STDOUT?

  20. 20

    子进程:stdout和stderror似乎互换或混合

  21. 21

    如何使用子进程和Popen从长时间运行的进程中返回stdout?

  22. 22

    Python子进程Popen传递参数

  23. 23

    在Python的子进程/ Popen中将stdout重定向到stderr

  24. 24

    Python子进程Popen stdout仅用于变量

  25. 25

    Python子进程没有正确的参数

  26. 26

    Python子进程抑制stdout和stderr

  27. 27

    带参数的Windows子进程

  28. 28

    将stdout重定向到文件时,正向子进程stdout不起作用

  29. 29

    带参数的 Python 子进程

热门标签

归档