当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


Node.js child_process.spawn(command[, args][, options])用法及代码示例


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

历史
版本变化
v16.4.0、v14.18.0

cwd 选项可以是使用 file: 协议的 WHATWG URL 对象。

v15.13.0、v14.18.0

添加了超时。

v15.11.0、v14.18.0

添加了AbortSignal 的 killSignal。

v15.5.0、v14.17.0

添加了AbortSignal 支持。

v13.2.0、v12.16.0

现在支持serialization 选项。

v8.8.0

现在支持windowsHide 选项。

v6.4.0

现在支持argv0 选项。

v5.7.0

现在支持shell 选项。

v0.1.90

添加于:v0.1.90


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

child_process.spawn() 方法使用给定的 command 生成一个新进程,在 args 中带有 命令行 参数。如果省略,args 默认为空数组。

如果启用了 shell 选项,请不要将未经处理的用户输入传递给此函数。任何包含 shell 元字符的输入都可用于触发任意命令执行。

第三个参数可用于指定其他选项,具有以下默认值:

const defaults = {
  cwd: undefined,
  env: process.env
};

使用cwd 指定生成进程的工作目录。如果没有给出,默认是继承当前工作目录。如果给定,但路径不存在,子进程会发出 ENOENT 错误并立即退出。 ENOENT 也会在命令不存在时发出。

使用 env 指定对新进程可见的环境变量,默认为 process.env

env 中的 undefined 值将被忽略。

运行 ls -lh /usr 、捕获 stdoutstderr 和退出代码的示例:

const { spawn } = require('node:child_process');
const ls = spawn('ls', ['-lh', '/usr']);

ls.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

ls.stderr.on('data', (data) => {
  console.error(`stderr: ${data}`);
});

ls.on('close', (code) => {
  console.log(`child process exited with code ${code}`);
});

示例:一种非常精细的运行方式ps ax | grep ssh

const { spawn } = require('node:child_process');
const ps = spawn('ps', ['ax']);
const grep = spawn('grep', ['ssh']);

ps.stdout.on('data', (data) => {
  grep.stdin.write(data);
});

ps.stderr.on('data', (data) => {
  console.error(`ps stderr: ${data}`);
});

ps.on('close', (code) => {
  if (code !== 0) {
    console.log(`ps process exited with code ${code}`);
  }
  grep.stdin.end();
});

grep.stdout.on('data', (data) => {
  console.log(data.toString());
});

grep.stderr.on('data', (data) => {
  console.error(`grep stderr: ${data}`);
});

grep.on('close', (code) => {
  if (code !== 0) {
    console.log(`grep process exited with code ${code}`);
  }
});

检查失败的示例 spawn

const { spawn } = require('node:child_process');
const subprocess = spawn('bad_command');

subprocess.on('error', (err) => {
  console.error('Failed to start subprocess.');
});

某些平台(macOS、Linux)将使用 argv[0] 的值作为进程标题,而其他平台(Windows、SunOS)将使用 command

Node.js 当前在启动时用process.execPath 覆盖argv[0],因此Node.js 子进程中的process.argv[0] 将不匹配从父进程传递给spawnargv0 参数,使用process.argv0 检索它而是属性。

如果启用了 signal 选项,则在相应的 AbortController 上调用 .abort() 与在子进程上调用 .kill() 类似,只是传递给回调的错误将是 AbortError

const { spawn } = require('node:child_process');
const controller = new AbortController();
const { signal } = controller;
const grep = spawn('grep', ['ssh'], { signal });
grep.on('error', (err) => {
  // This will be called with err being an AbortError if the controller aborts
});
controller.abort(); // Stops the child process

options.detached#

添加于:v0.7.10

在 Windows 上,将 options.detached 设置为 true 可以让子进程在父进程退出后继续运行。孩子将拥有自己的控制台窗口。一旦为子进程启用,它就不能被禁用。

在非 Windows 平台上,如果 options.detached 设置为 true ,则子进程将成为新进程组和会话的领导者。子进程可以在父进程退出后继续运行,无论它们是否分离。有关详细信息,请参阅 setsid(2)

默认情况下,父级将等待分离的子级退出。要防止父级等待给定的subprocess 退出,请使用subprocess.unref() 方法。这样做会导致父级的事件循环不将子级包含在其引用计数中,从而允许父级独立于子级退出,除非子级和父级之间已建立 IPC 通道。

当使用detached 选项启动long-running 进程时,进程将不会在父进程退出后继续在后台运行,除非它提供了未连接到父进程的stdio 配置。如果继承父级的stdio,则子级将保持连接到控制终端。

long-running 进程的示例,通过分离并忽略其父 stdio 文件说明符,以忽略父进程的终止:

const { spawn } = require('node:child_process');

const subprocess = spawn(process.argv[0], ['child_program.js'], {
  detached: true,
  stdio: 'ignore'
});

subprocess.unref();

或者,可以将子进程的输出重定向到文件中:

const fs = require('node:fs');
const { spawn } = require('node:child_process');
const out = fs.openSync('./out.log', 'a');
const err = fs.openSync('./out.log', 'a');

const subprocess = spawn('prg', [], {
  detached: true,
  stdio: [ 'ignore', out, err ]
});

subprocess.unref();

options.stdio#

历史
版本变化
v15.6.0、v14.18.0

添加了overlapped stdio 标志。

v3.3.1

0 现在被接受为文件说明符。

v0.7.10

添加于:v0.7.10

options.stdio 选项用于配置在父进程和子进程之间建立的管道。默认情况下,孩子的 stdin、stdout 和 stderr 被重定向到 ChildProcess 对象上相应的 subprocess.stdin subprocess.stdout subprocess.stderr 流。这相当于将 options.stdio 设置为等于 ['pipe', 'pipe', 'pipe']

为方便起见,options.stdio 可能是以下字符串之一:

  • 'pipe' :相当于['pipe', 'pipe', 'pipe'](默认)
  • 'overlapped' :相当于['overlapped', 'overlapped', 'overlapped']
  • 'ignore' :相当于['ignore', 'ignore', 'ignore']
  • 'inherit' :等同于 ['inherit', 'inherit', 'inherit'][0, 1, 2]

否则,options.stdio 的值是一个数组,其中每个索引对应于子项中的一个 fd。 fds 0、1 和 2 分别对应于 stdin、stdout 和 stderr。可以指定额外的 fd 来在父子节点之间创建额外的管道。该值为以下之一:

  1. 'pipe' :在子进程和父进程之间创建一个管道。管道的父端作为 child_process 对象上的属性公开给父级,为 subprocess.stdio[fd] 。为 fds 0、1 和 2 创建的管道也可分别用作 subprocess.stdin subprocess.stdout subprocess.stderr 。目前,这些不是实际的 Unix 管道,因此子进程不能通过它们的说明符文件使用它们,例如/dev/fd/2/dev/stdout

  2. 'overlapped' :与 'pipe' 相同,只是在句柄上设置了 FILE_FLAG_OVERLAPPED 标志。这对于子进程的 stdio 句柄上的重叠 I/O 是必要的。有关详细信息,请参阅docs。这与非 Windows 系统上的 'pipe' 完全相同。

  3. 'ipc':创建一个 IPC 通道,用于在父子之间传递消息/文件说明符。 ChildProcess 最多可以有一个 IPC stdio 文件说明符。设置此选项将启用 subprocess.send() 方法。如果子进程是 Node.js 进程,则 IPC 通道的存在将启用 process.send() process.disconnect() 方法,以及子进程内的 'disconnect' 'message' 事件。

    不支持以 process.send() 以外的任何方式访问 IPC 通道 fd 或将 IPC 通道与不是 Node.js 实例的子进程一起使用。

  4. 'ignore' :指示 Node.js 忽略子级中的 fd。虽然 Node.js 将始终为其生成的进程打开 fds 0、1 和 2,但将 fd 设置为 'ignore' 将导致 Node.js 打开 /dev/null 并将其附加到子 fd 上。

  5. 'inherit' :通过相应的 stdio 流传入/传出父进程。在前三个位置,这分别相当于 process.stdinprocess.stdoutprocess.stderr 。在任何其他位置,相当于 'ignore'

  6. <Stream> 对象:与子进程共享引用 tty、文件、套接字或管道的可读或可写流。流的底层文件说明符在子进程中复制到与 stdio 数组中的索引对应的 fd。流必须有一个底层说明符(文件流在 'open' 事件发生之前没有)。

  7. 正整数:整数值被解释为当前在父进程中打开的文件说明符。它与子进程共享,类似于如何共享 <Stream> 对象。 Windows 不支持传递套接字。

  8. null , undefined :使用默认值。对于 stdio fds 0、1 和 2(换句话说,stdin、stdout 和 stderr)创建了一个管道。对于 fd 3 及更高版本,默认值为 'ignore'

const { spawn } = require('node:child_process');

// Child will use parent's stdios.
spawn('prg', [], { stdio: 'inherit' });

// Spawn child sharing only stderr.
spawn('prg', [], { stdio: ['pipe', 'pipe', process.stderr] });

// Open an extra fd=4, to interact with programs presenting a
// startd-style interface.
spawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] });

值得注意的是,当父子进程之间建立了 IPC 通道,并且子进程是 Node.js 进程时,子进程会以未引用的 IPC 通道启动(使用 unref() ),直到子进程注册事件处理程序对于 'disconnect' 事件或 'message' 事件。这允许子进程正常退出,而进程不会被打开的 IPC 通道保持打开状态。

在Unix-like 操作系统上, child_process.spawn() 方法在将事件循环与子进程分离之前同步执行内存操作。具有大量内存占用的应用程序可能会发现频繁的 child_process.spawn() 调用是一个瓶颈。有关详细信息,请参阅V8 issue 7381

另请参阅: child_process.exec() child_process.fork()

相关用法


注:本文由纯净天空筛选整理自nodejs.org大神的英文原创作品 child_process.spawn(command[, args][, options])。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。