Node.js child_process.spawn

🌙
手机阅读
本文目录结构

Node.js child_process.spawn(command[, args][, options]) 版本历史

版本 变更
v8.8.0 The windowsHide option is supported now.
v6.4.0 The argv0 option is supported now.
v5.7.0 The shell option is supported now.
v0.1.90 新增于: v0.1.90
  • command < string> 要运行的命令。

  • args < string[]> 字符串参数的列表。

  • options < Object>

    • cwd < string> 子进程的当前工作目录。
    • env < Object> 环境变量的键值对。
    • argv0 < string> 显式设置发送给子进程的 argv[0] 的值。如果没有指定,则设置为 command 的值。
    • stdio < Array> | < string> 子进程的 stdio 配置。参阅 options.stdio。
    • detached < boolean> 准备子进程独立于其父进程运行。具体行为取决于平台,参阅 options.detached。
    • uid < number> 设置进程的用户标识,参阅 setuid(2)。
    • gid < number> 设置进程的群组标识,参阅 setgid(2)。
    • shell < boolean> | < string> 如果为 true,则在 shell 中运行 command。 在 UNIX 上使用 ‘/bin/sh’,在 Windows 上使用 - process.env.ComSpec。 传入字符串则指定其他 shell。 参阅 shell 的要求与 Windows 默认的 shell。 默认值: false(没有 shell)。
    • windowsVerbatimArguments < boolean> 在 Windows 上是否为参数加上引号或转义。在 Unix 上忽略。如果指定了 shell,则自动设为 true。默认值: false。
    • windowsHide < boolean> 隐藏通常在 Windows 系统上创建的子进程的控制台窗口。默认值: false。
  • 返回: < ChildProcess>

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

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

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

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

使用 cwd 指定衍生进程的工作目录。 如果没有给出,则默认为继承当前工作目录。

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

env 中的 undefined 值会被忽略。

示例,运行 ls -lh /usr,并捕获 stdout、 stderr、以及退出码:

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}`);
});

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

const { spawn } = require('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.log(`ps stderr: ${data}`);
});

ps.on('close', (code) => {
  if (code !== 0) {
    console.log(`ps 进程的退出码:${code}`);
  }
  grep.stdin.end();
});

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

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

grep.on('close', (code) => {
  if (code !== 0) {
    console.log(`grep 进程的退出码:${code}`);
  }
});

示例,检查失败的 spawn:

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

subprocess.on('error', (err) => {
  console.log('无法启动子进程');
});

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

Node.js 一般会在启动时用 process.execPath 覆盖 argv[0],因此 Node.js 子进程的 process.argv[0] 与从父进程传给 spawn 的 argv0 参数不会匹配,可以使用 process.argv0 属性获取。

options.detached

新增于: v0.7.10

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

在非 Windows 平台上,如果 options.detached 设为 true,则子进程会成为新的进程组和会话的领导者。 子进程在父进程退出后可以继续运行,不管它们是否被分离。 详见 setsid(2)。

默认情况下,父进程会等待被分离的子进程退出。 为了防止父进程等待 subprocess,可以使用 subprocess.unref()。 这样做会导致父进程的事件循环不包含子进程的引用计数,使得父进程独立于子进程退出,除非子进程和父进程之间建立了一个 IPC 信道。

当使用 detached 选项来启动一个长期运行的进程时,该进程不会在父进程退出后保持在后台运行,除非指定一个不连接到父进程的 stdio 配置。 如果父进程的 stdio 是继承的,则子进程会保持连接到控制终端。

例子,一个长期运行的进程,为了忽视父进程的终止,通过分离且忽视其父进程的 stdio 文件描述符来实现:

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

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

subprocess.unref();

也可以将子进程的输出重定向到文件:

const fs = require('fs');
const { spawn } = require('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

版本历史

版本 变更
v3.3.1 The value 0 is now accepted as a file descriptor.
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’](默认值)。
  • ‘ignore’ - 相当于 [‘ignore’, ‘ignore’, ‘ignore’]。
  • ‘inherit’ - 相当于 [‘inherit’, ‘inherit’, ‘inherit’] 或 [0, 1, 2]。

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

  1. ‘pipe’ - 在子进程和父进程之间创建一个管道。 管道的父端作为 child_process 对象上的属性 subprocess.stdio[fd] 暴露给父进程。 为 fd 0 - 2 创建的管道也可分别作为 subprocess.stdin、subprocess.stdout 和 subprocess.stderr 使用。

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

    不支持以 process.send() 以外的任何方式访问 IPC 通道 fd,或者使用不具有 Node.js 实例的子进程使用 IPC 通道。

  3. ‘ignore’ - 指示 Node.js 忽略子进程中的 fd。 虽然 Node.js 将始终为它衍生的进程打开 fd 0 - 2,但将 fd 设置为 ‘ignore’ 将导致 Node.js 打开 /dev/null 并将其附加到子进程的 fd。

  4. ‘inherit’ - 将相应的 stdio 流传给父进程或从父进程传入。 在前三个位置,这分别相当于 process.stdin、 process.stdout 与 process.stderr。 在任何其他位置则相当于 ‘ignore’。

  5. < Stream> 对象 - 与子进程共享指向 tty、文件、套接字或管道的可读或可写流。 流的底层文件描述符在子进程中复制到与 stdio 数组中的索引对应的 fd。 注意,流必须具有底层描述符(文件流直到触发 ‘open’ 事件才需要)。

  6. 正整数 - 整数值被解释为当前在父进程中打开的文件描述符。 它与子进程共享,类似于共享 < stream> 对象。

  7. null 或 undefined - 使用默认值。 对于 stdio 的 fd 0、1 和 2(换句话说,stdin、stdout 和 stderr),将创建一个管道。 对于 fd 3 及更高版本,默认为 ‘ignore’。

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

// 子进程使用父进程的 stdio。
spawn('prg', [], { stdio: 'inherit' });

// 衍生的子进程只共享 stderr。
spawn('prg', [], { stdio: ['pipe', 'pipe', process.stderr] });

// 打开一个额外的 fd=4,与呈现启动式界面的程序进行交互。
spawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] });

注意,当在父进程和子进程之间建立 IPC 通道,并且子进程是 Node.js 进程时,子进程在未指向(使用 unref())IPC 通道的情况下启动直到子进程注册事件处理函数用于 ‘disconnect’ 事件或 ‘message’ 事件。 这允许子进程正常退出而不需要通过开放的 IPC 通道保持打开该进程。

在类 UNIX 操作系统上,child_process.spawn() 方法在将事件循环与子进程解耦之前会同步地执行内存操作。 具有大内存占用的应用程序可能会发现频繁的 child_process.spawn() 调用成为瓶颈。 有关更多信息,参阅 V8 问题 7381。

还可参阅:child_process.exec() 和 child_process.fork()。


更多内容请参考:Node.js child_process 子进程,或者通过 点击对应菜单 进行查看;



AXIHE / 精选资源

浏览全部教程

面试题

学习网站

前端培训
自己甄别

前端书籍

关于朱安邦

我叫 朱安邦,阿西河的站长,在杭州。

以前是一名平面设计师,后来开始接接触前端开发,主要研究前端技术中的JS方向。

业余时间我喜欢分享和交流自己的技术,欢迎大家关注我的 Bilibili

关注我: Github / 知乎

目前重心已经放在研究区块链上面了

我叫朱安邦,阿西河的站长

目前在杭州从事区块链周边的开发工作,机械专业,以前从事平面设计工作。

2014年底脱产在老家自学6个月的前端技术,自学期间几乎从未出过家门,最终找到了满意的前端工作。更多>