Node.js中child_process模块中spawn与exec的异同比较
Node.js基于事件驱动来处理并发,它本身是以单线程模式运行的。Node.js通过
child_process
开启子进程执行指定程序。主要包括4个异步进程函数(spawn,exec,execFile,fork)和3个同步进程函数(spawnSync,execFileSync,execSync)。一般我们比较常用的是spawn和exec这两个方法。其中异步进程函数spawn是最基本的创建子进程的函数,其他三个异步函数都是对spawn不同程度的封装。spawn只能运行指定的程序,参数需要在列表中给出,而exec可以直接运行复杂的命令。
默认情况下,
stdin
、
stdout
和
stderr
的管道在父 Node.js 进程和衍生的子进程之间建立。这些管道具有有限的(与平台相关)容量。 如果子进程在没有捕获输出的情况下写入超出该限制的 stdout,则子进程将阻塞等待管道缓冲区接受更多的数据。 这与 shell 中的管道行为相同。 如果不需要输出,则使用
{ stdio: 'ignore' }
child_process.spawn
方法异步地衍生子进程,并且不阻塞 Node.js 事件循环。而
child_process.spawnSync
方法则以同步的方式提供等效功能,但会阻止事件循环直到衍生的进程退出或终止。
为方便起见,
child_process
模块提供了
child_process.spawn()
和
child_process.spawnSync()
的一些同步和异步的替代方法。注意,这些替代方法中的每一个都是基于
child_process.spawn()
或
child_process.spawnSync()
实现的。
-
child_process.exec()
:衍生一个 shell 并在该 shell 中运行命令,当完成时则将stdout
和stderr
传给回调函数。 -
child_process.execFile()
:类似于child_process.exec()
,除了它默认会直接衍生命令且不首先衍生 shell。 -
child_process.fork()
:衍生一个新的 Node.js 进程,并通过建立 IPC 通信通道来调用指定的模块,该通道允许在父进程与子进程之间发送消。 -
child_process.execSync()
:child_process.exec()
的同步版本,会阻塞 Node.js 事件循环。 -
child_process.execFileSync()
:child_process.execFile()
的同步版本,会阻塞 Node.js 事件循环。
对于某些用例,例如自动化的 shell 脚本,
同步的方法
可能更方便。 但是在大多数情况下,同步的方法会对性能产生重大影响,因为它会停止事件循环直到衍生的进程完成。
child_process.spawn(command[, args][, options])
const { spawn } = require('child_process');
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(`子进程退出码:${code}`);
child_process.exec(command[, options], callback)
const { exec } = require('child_process');
exec('cat *.js missing_file | wc -l', (error, stdout, stderr) => {
if (error) {
console.error(`执行出错: ${error}`);