阿西河

所有教程

公众号
🌙
阿西河前端的公众号

我的收藏

    最近访问  (文章)

      教程列表

      抓包专区
      测试专区

      Node.js child_process.spawn

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

      版本变更
      v8.8.0The windowsHide option is supported now.
      v6.4.0The argv0 option is supported now.
      v5.7.0The 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.1The 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 子进程,或者通过 点击对应菜单 进行查看;


      目录
      目录