gpt4 book ai didi

node.js - 子进程 : The stdout parameter

转载 作者:搜寻专家 更新时间:2023-10-31 23:13:39 25 4
gpt4 key购买 nike

根据文档,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 source code表明,从 0.10.18 开始,stdout 始终是一个字符串。如果要获取二进制数据,则必须使用 spawn

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

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

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

编辑:代码示例取自 master,还不是稳定版本。

编辑 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;
};

关于node.js - 子进程 : The stdout parameter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18925426/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com