Skip to content

child_process 子进程

child_process 是 Node.js 核心模块,它提供了在 node.js 执行脚本以及shell命令的强大功能。 创建子进程共有 7 个 API,它们分别为:

  • spawn 异步执行命令
  • spawnSync 同步执行命令
  • exec 执行命令
  • execSync 同步执行命令
  • execFile 执行可执行文件
  • execFileSync 同步执行可执行文件
  • fort 创建 node 子进程

提示

在 node.js 中(后续包括 fs)一般的在方法后面带上Sync都是同步的行为,具体在使用异步或者同步需要根据不同场景下做出不同的使用。

exec & execSync

exec

js
exec(command, [options], callback);
exec(command, [options], callback);

exec 一般适用于简单的shell命令,因为它有返回大小的限制,它返回是一个buffer。方法对应参数分别为:

  • command <string> 要运行的命令,参数以空格分离
  • options <Object>
    • cwd <string> | <URL> 子进程的当前工作目录。 默认值: process.cwd()。
    • env <Object> 环境变量键值对。 默认值: process.env。
    • encoding <string> 默认值: 'utf8'
    • shell <string> 用于执行命令的 shell。 请参阅 shell 的要求和默认的 Windows shell。 默认值: Unix 上是 '/bin/sh',Windows 上是 process.env.ComSpec。
    • signal <AbortSignal> 允许使用中止信号中止子进程。
    • timeout <number> 默认值: 0
    • maxBuffer <number> 标准输出或标准错误上允许的最大数据量(以字节为单位)。 如果超过,则子进程将终止并截断任何输出。 请参阅 maxBuffer 和 Unicode 的注意事项。 默认值: 1024 * 1024。
    • killSignal <string> | <integer> 默认值: 'SIGTERM'
    • uid <number> 设置进程的用户标识(参见 setuid(2))。
    • gid <number> 设置进程的群组标识(参见 setgid(2))。
    • windowsHide <boolean> 隐藏通常在 Windows 系统上创建的子进程控制台窗口。 默认值: false。
  • callback <Function> 当进程终止时使用输出调用。
    • error <Error> 报错
    • stdout <string> | <Buffer> 成功流
    • stderr <string> | <Buffer> 失败流

举一个例子,现在快速利用exec来快速实现一个node -v

js
import { exec } from "node:child_process";

exec("node -v", (err, stdout, stderr) => {
  if (err) return err;
  console.log(stdout.toString()); // log ---> v20.2.0
});
import { exec } from "node:child_process";

exec("node -v", (err, stdout, stderr) => {
  if (err) return err;
  console.log(stdout.toString()); // log ---> v20.2.0
});

特别提示

使用exec或者execSync的时候,务必需要验证用户传进来的shell命令。

execSync

js
execSync(command[, options])
execSync(command[, options])

execSyncexec的同步方法,它与exec的使用方法类似,无非少了回调函数,用上述例子快速使用execSync来实现一个node -v;

js
console.log(execSync("node -v").toString()); // log ---> v20.2.0
console.log(execSync("node -v").toString()); // log ---> v20.2.0

只要是当前操作系统能支持的shell命令,execexecSync都可以支持执行。

spawn & spawnSync

spawnexec的最大区别就是spawn没有限制上线,它更适合对一些复杂而去耗时的shell命令进行操作,虽然它有同步的用法,但一般会比较少用,毕竟 node.js 是单线程,如果spawnSync进程卡死,那将会导致整个进程堵塞。

spawnSync

用法:

js
spawnSync(command[, args][, options])
spawnSync(command[, args][, options])

command 即为将要执行的shell命令,然后后面分别为参数和配置,因为该方法为同步方法,如果命名执行时间过于长的情况下,会导致整个进程堵塞。所以一般情况下都是使用spwan进行操作。

spawn

用法:

js
spawn(command[, args][, options])
spawn(command[, args][, options])

spawn是异步的事件,但它对比exec通过回调函数获取异步结果有所不同,它更多类似于“发布订阅”的即时感,它需要通过监听ondata获取实时返回的数据,而当整个异步事件结束后,它会在on中暴露一个close的钩子函数来告诉开发者,这次的异步事件已经执行完毕。

js
// index.js
const { stdout } = spawn("netstat"); // netstat 是获取当前网路信息

stdout.on("data", (reuslt) => {
  console.log(result, "这是一个实时返回的流");
});

stdout.on("close", () => {
  console.log("执行完毕");
});
// index.js
const { stdout } = spawn("netstat"); // netstat 是获取当前网路信息

stdout.on("data", (reuslt) => {
  console.log(result, "这是一个实时返回的流");
});

stdout.on("close", () => {
  console.log("执行完毕");
});

当然的,spawn也是支持传递参数以及配置属性,spawn第二个参数为我们需要传递的参数,第三个为配置项

js
const { stdout } = spawn("netstat", "-v", options);
const { stdout } = spawn("netstat", "-v", options);

具体支持的配置如下:

  • command <string> 要运行的命令。
  • args <string[]> 字符串参数列表。
  • options <Object>
    • cwd <string> | <URL> 子进程的当前工作目录。
    • env <Object> 环境变量键值对。 默认值: process.env。
    • argv0 <string> 显式设置发送给子进程的 argv[0] 的值。 如果未指定,这将设置为 command。
    • stdio <Array> | <string> 子进程的标准输入输出配置(参见 options.stdio)。
    • detached <boolean> 准备子进程独立于其父进程运行。 具体行为取决于平台,参见 options.detached。
    • uid <number> 设置进程的用户标识(参见 setuid(2))。
    • gid <number> 设置进程的群组标识(参见 setgid(2))。
    • serialization <string> 指定用于在进程之间发送消息的序列化类型。 可能的值为 'json' 和 'advanced'。 有关更多详细信息,请参阅高级序列化。 默认值: 'json'。
    • shell <boolean> | <string> 如果是 true,则在 shell 内运行 command。 在 Unix 上使用 '/bin/sh',在 Windows 上使用 process.env.ComSpec。 可以将不同的 shell 指 - 定为字符串。 请参阅 shell 的要求和默认的 Windows shell。 默认值: false (没有 shell)
    • windowsVerbatimArguments <boolean> 在 Windows 上不为参数加上引号或转义。 在 Unix 上被忽略。 当指定了 shell 并且是 CMD 时,则自动设置为 true。 默认值: false。
    • windowsHide <boolean> 隐藏通常在 Windows 系统上创建的子进程控制台窗口。 默认值: false。
    • signal <AbortSignal> 允许使用中止信号中止子进程。
    • timeout <number> 允许进程运行的最长时间(以毫秒为单位)。 默认值: undefined。
    • killSignal <string> | <integer> 当衍生的进程将被超时或中止信号杀死时要使用的信号值。 默认值: 'SIGTERM'。

特别提示

使用spwan或者spwanSync的时候,务必需要验证用户传进来的shell命令。

execFile && execFileSync

execFileexecFileSync 都是执行指定的可执行文件的file直接作为新进程衍生,使其比execexecSync略有效率。简单的说,execFileexecFileSync 就是处理shell命令文件的 Api。

execFile

js
execFile(file[, args][, options][, callback])
execFile(file[, args][, options][, callback])

用法还是和普通的exec类似,举个例子,假设现在项目根目录有file.sh文件。

js
execFile("/file.sh", (err, stdout, stderr) => {
  if (err) return;
  console.log(stdout.toString());
})``;
execFile("/file.sh", (err, stdout, stderr) => {
  if (err) return;
  console.log(stdout.toString());
})``;

execFileSync

js
execFileSync(file[, args][, options])
execFileSync(file[, args][, options])

同步模式就也与普通的execSync类似,还是假设现在项目根目录有file.sh文件。

js
const { stdout } = execFileSync("/file.sh");
console.log(stdout.toString());
const { stdout } = execFileSync("/file.sh");
console.log(stdout.toString());

fork

js
fork(modulePath[, args][, options])
fork(modulePath[, args][, options])

fork是创建一个只执行 js的 Nodejs 子进程,专门用于衍生新的 Node.js 进程。 与 child_process.spawn() 一样,返回 ChildProcess 对象。 返回的 ChildProcess 将有额外的内置通信通道,允许消息在父进程和子进程之间来回传递。 详见 subprocess.send()。衍生的 Node.js 子进程独立于父进程,除了两者之间建立的 IPC 通信通道。 每个进程都有自己的内存,具有自己的 V8 实例。 由于需要额外的资源分配,不建议衍生大量子 Node.js 进程。 简单的说,它可以实现父进程向子进程通信,或者子向父通信,同时执行子进程内的程序。

举个例子,现在假设有父进程 a,子进程 b;

js
// 父进程 a.js
const result = fork("/b.js");

result.send("我是父进程"); // 向子进程通信

// 子进程 b.js
result.on("message", (mes) => {
  console.log("子进程收到消息");
});
// 父进程 a.js
const result = fork("/b.js");

result.send("我是父进程"); // 向子进程通信

// 子进程 b.js
result.on("message", (mes) => {
  console.log("子进程收到消息");
});

当然的,也可以子进程,启用send事件向父进程通信。

更多 Api

子进程这块还是很庞大,更多 api 还是需要找到官方文档