Node.js 创建子进程的几种实现方式

作者:慢半拍时间:2026-10-31 07:33:37浏览:591

本文详细介绍 Node.js 中创建子进程的四种核心方法:exec、execFile、fork 和 spawn。重点解析各方法的适用场景、参数配置及父子进程间的通信机制,特别是 stdio 管道选项(pipe、ignore、inherit)的具体行为与默认设置,帮助开发者根据实际需求选择最优方案。

exec

exec 函数允许在指定的 Shell 环境中执行系统命令。

该函数接受以空格分隔的参数,适用于构建较为复杂的命令字符串。

const { exec } = require('child_process')
exec('cat *.js bad_file | wc -l')

exec 方法用于异步创建一个新的子进程,并支持接收回调函数。

exec('cat *.js bad_file | wc -l', (err, stdout, stderr) => {
  console.log(stdout)
})

传递给回调函数的 stdout 和 stderr 参数将包含子进程的标准输出和标准错误输出内容。

execFile

child_process.execFile(file[, args][, options][, callback])
const { execFile } = require('child_process')
execFile('node', ['--version'], (err, stdout, stderr) => {
  console.log(stdout)
})

execFile 不会直接衍生一个 Shell 进程。

它直接指定可执行文件来创建一个新的进程,从而避免 Shell 解析带来的开销。

fork

child_process.fork(modulePath[, args][, options])

fork 方法用于创建一个新的 Node.js 子进程,调用后返回一个子进程对象。

通过 fork 创建的子进程可以与父进程利用内置的 IPC(进程间通信)通道进行数据交换。

衍生出的 Node.js 子进程与其建立的 IPC 通信信道异常处理机制独立于父进程。

每个衍生出的进程都拥有独立的内存空间,并使用各自的 V8 引擎实例。

由于衍生进程需要分配额外的系统资源,因此不建议衍生大量的 Node.js 进程。

在 options 配置对象中,包含以下关键配置项:

silent

该配置用于控制父子进程间 stdin、stdout 和 stderr 的通信行为。

若将其设置为 true,子进程的标准输入和输出将被重定向到父进程中。

parent.js
const { fork } = require('child_process')
const fd = fork('./sub.js')
 
fd.stdout.on('data', data => console.log(data))
 
sub.js
console.log('this is sub process')

当子进程需要处理 stdin 输入时,可将其直接导入父进程,从而实现与 tty 或 Shell 的交互。

若设置为 false,子进程的标准输入输出将直接继承父进程的设置。

stdio

关于该配置的具体用法详见下文说明。

spawn

child_process.spawn(command[, args][, options])

前文提到的 exec、execFile 和 fork 创建新子进程的方法,底层均基于 spawn 方法进行封装。

调用该方法会返回一个子进程对象。

父子进程间的通讯

在使用 fork 和 spawn 创建子进程时,配置选项中包含一个关于 stdio 的字段。

该字段主要用于配置父子进程间的管道连接方式。

默认情况下,子进程的 stdin、stdout 和 stderr 会被重定向到 ChildProcess 对象上对应的 subprocess.stdin、subprocess.stdout 和 subprocess.stderr 流。

这种默认行为等同于将 options.stdio 设置为 ['pipe', 'pipe', 'pipe']。

  • pipe:等同于 [pipe, pipe, pipe] (默认)
  • ignore:等同于 [ignore, ignore, ignore]
  • inherit:等同于 [process.stdin, process.stdout, process.stderr] 或 [0,1,2]

其中 inherit 表示继承父进程的标准输入输出,即与父进程共享这些流。

const { spawn } = require('child_process');
 
// 子进程使用父进程的 stdios
spawn('prg', [], { stdio: 'inherit' });
 
// 衍生的子进程只共享 stderr
spawn('prg', [], { stdio: ['pipe', 'pipe', process.stderr] });
 
// 打开一个额外的 fd=4,用于与程序交互
spawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] });

总结

以上为个人经验总结,希望能给大家一个参考,也希望大家多多支持本站。

作者最新文章