We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
const exec = require('child_process').exec; exec('cat *.js bad_file | wc -l', (error, stdout, stderr) => { if (error) { console.error(`exec error: ${error}`); return; } console.log(`stdout: ${stdout}`); console.log(`stderr: ${stderr}`); });
const spawn = require('child_process').spawn; const ls = spawn('ls', ['-lh', '/usr']); ls.stdout.on('data', (data) => { console.log(`stdout: ${data}`); }); ls.stderr.on('data', (data) => { console.log(`stderr: ${data}`); }); ls.on('close', (code) => { console.log(`child process exited with code ${code}`); });
exec()默认参数:
const defaults = { encoding: 'utf8', timeout: 0, maxBuffer: 200*1024, killSignal: 'SIGTERM', cwd: null, env: null };
spawn()默认参数:
const defaults = { cwd: undefined, env: process.env };
详见源码:
exports.exec = function(command /*, options, callback*/) { var opts = normalizeExecArgs.apply(null, arguments); return exports.execFile(opts.file, opts.args, opts.options, opts.callback); };
exec对于execFile的封装是进行参数处理
处理的函数:
normalizeExecArgs
if (process.platform === 'win32') { file = process.env.comspec || '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]; }
感觉这个处理和我的想法很像...
将简单的command命名做一个,win和linux的平台处理。
此时execFile接受到的就是一个区分平台的command参数。
然后重点来了,继续debug,execFile中:
var options = { encoding: 'utf8', timeout: 0, maxBuffer: 200 * 1024, killSignal: 'SIGTERM', cwd: null, env: null };
有这么一段,设置了默认的参数。然后后面又是一些参数处理,最后调用spawn方法启动子进程。
上面的简单流程就是启动一个子进程。到这里都没有什么问题。
继续看,重点又来了:
用过子进程应该知道这个child.stderr
下面的代码就解答了为什么子进程会挂掉。
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; } });
逻辑就是,记录子进程的log大小,一旦超过maxBuffer就kill掉子进程。
原来真相在这里。我们在使用exec时,不知道设置maxBuffer,默认的maxBuffer是200K,当我们子进程日志达到200K时,自动kill()掉了。
这也正是exec()与spawn()最大的区别: exec()限制了maxBuffer默认为200k,超过时会自动kill子进程,并报"maxBuffer exceeded"异常
参考文献:https://www.hacksparrow.com/difference-between-spawn-and-exec-of-node-js-child_process.html
使用node子进程spawn-exec踩过的坑
The text was updated successfully, but these errors were encountered:
No branches or pull requests
exec()官方示例:
spawn()官方示例:
exec() 和 spawn() 的区别:
exec()默认参数:
spawn()默认参数:
exec是对execFile的封装,execFile又是对spawn的封装。
详见源码:
exec对于execFile的封装是进行参数处理
处理的函数:
normalizeExecArgs
将简单的command命名做一个,win和linux的平台处理。
此时execFile接受到的就是一个区分平台的command参数。
然后重点来了,继续debug,execFile中:
有这么一段,设置了默认的参数。然后后面又是一些参数处理,最后调用spawn方法启动子进程。
上面的简单流程就是启动一个子进程。到这里都没有什么问题。
继续看,重点又来了:
用过子进程应该知道这个child.stderr
下面的代码就解答了为什么子进程会挂掉。
逻辑就是,记录子进程的log大小,一旦超过maxBuffer就kill掉子进程。
原来真相在这里。我们在使用exec时,不知道设置maxBuffer,默认的maxBuffer是200K,当我们子进程日志达到200K时,自动kill()掉了。
参考文献:https://www.hacksparrow.com/difference-between-spawn-and-exec-of-node-js-child_process.html
使用node子进程spawn-exec踩过的坑
The text was updated successfully, but these errors were encountered: