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


  • 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'。更多详情请参见 高级序列化默认值: '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> 允许使用 AbortSignal 中止子进程。
    • timeout <number> 进程允许运行的最长时间(毫秒)。默认值: undefined
    • killSignal <string> | <integer> 当被生成的进程因超时或中止信号而被终止时使用的信号值。默认值: 'SIGTERM'
  • 返回:<ChildProcess>

child_process.spawn() 方法使用给定的 command 创建一个新进程,args 中提供命令行参数。如果省略,args 默认是一个空数组。

【The child_process.spawn() method spawns a new process using the given command, with command-line arguments in args. If omitted, args defaults to an empty array.】

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

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

【A third argument may be used to specify additional options, with these defaults:】

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

使用 cwd 来指定进程启动时的工作目录。如果未指定,默认会继承当前工作目录。如果指定了路径,但路径不存在,子进程会发出 ENOENT 错误并立即退出。当命令不存在时,也会发出 ENOENT 错误。

【Use cwd to specify the working directory from which the process is spawned. If not given, the default is to inherit the current working directory. If given, but the path does not exist, the child process emits an ENOENT error and exits immediately. ENOENT is also emitted when the command does not exist.】

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

【Use env to specify environment variables that will be visible to the new process, the default is process.env.】

env 中的 undefined 值将被忽略。

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

【Example of running ls -lh /usr, capturing stdout, stderr, and the exit code:】

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}`);
});import { spawn } from '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 的一种非常复杂的方式

【Example: A very elaborate way to run 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}`);
  }
});import { spawn } from '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 失败的示例:

【Example of checking for failed spawn:】

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

subprocess.on('error', (err) => {
  console.error('Failed to start subprocess.');
});import { spawn } from '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

【Certain platforms (macOS, Linux) will use the value of argv[0] for the process title while others (Windows, SunOS) will use command.】

Node.js 在启动时会将 argv[0] 覆盖为 process.execPath,因此 Node.js 子进程中的 process.argv[0] 不会与父进程通过 spawn 传递的 argv0 参数匹配。请改为使用 process.argv0 属性来获取它。

【Node.js overwrites argv[0] with process.execPath on startup, so process.argv[0] in a Node.js child process will not match the argv0 parameter passed to spawn from the parent. Retrieve it with the process.argv0 property instead.】

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

【If the signal option is enabled, calling .abort() on the corresponding AbortController is similar to calling .kill() on the child process except the error passed to the callback will be an 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 processimport { spawn } from '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