當前位置: 首頁>>代碼示例 >>用法及示例精選 >>正文


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])。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。