Node.js v21.7.2 文件
- Node.js v21.7.2
-
► 目錄
- 子程序
- 非同步程序建立
- 同步程序建立
- 類別:
ChildProcess
- 事件:
'close'
- 事件:
'disconnect'
- 事件:
'error'
- 事件:
'exit'
- 事件:
'message'
- 事件:
'spawn'
subprocess.channel
subprocess.connected
subprocess.disconnect()
subprocess.exitCode
subprocess.kill([signal])
subprocess[Symbol.dispose]()
subprocess.killed
subprocess.pid
subprocess.ref()
subprocess.send(message[, sendHandle[, options]][, callback])
subprocess.signalCode
subprocess.spawnargs
subprocess.spawnfile
subprocess.stderr
subprocess.stdin
subprocess.stdio
subprocess.stdout
subprocess.unref()
- 事件:
maxBuffer
和 Unicode- Shell 需求
- 預設 Windows shell
- 進階序列化
- 子程序
-
► 索引
- 斷言測試
- 非同步背景追蹤
- 非同步掛鉤
- 緩衝區
- C++ 外掛程式
- 使用 Node-API 的 C/C++ 外掛程式
- C++ 嵌入式 API
- 子程序
- 叢集
- 命令列選項
- 主控台
- Corepack
- 加密
- 偵錯程式
- 已棄用的 API
- 診斷頻道
- DNS
- 網域
- 錯誤
- 事件
- 檔案系統
- 全域變數
- HTTP
- HTTP/2
- HTTPS
- 檢查器
- 國際化
- 模組:CommonJS 模組
- 模組:ECMAScript 模組
- 模組:
node:module
API - 模組:套件
- 網路
- 作業系統
- 路徑
- 效能掛鉤
- 權限
- 程序
- Punycode
- 查詢字串
- Readline
- REPL
- 報告
- 單一可執行應用程式
- 串流
- 字串解碼器
- 測試執行器
- 計時器
- TLS/SSL
- 追蹤事件
- TTY
- UDP/資料報
- URL
- 公用程式
- V8
- VM
- WASI
- Web Crypto API
- Web Streams API
- 工作執行緒
- Zlib
- ► 其他版本
- ► 選項
子程序#
原始碼: lib/child_process.js
node:child_process
模組提供以類似於 popen(3)
的方式產生子程序的能力,但並非完全相同。此功能主要由 child_process.spawn()
函數提供
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}`);
});
預設情況下,會在父項 Node.js 程序和產生的子程序之間建立 stdin
、stdout
和 stderr
的管道。這些管道的容量有限(且因平台而異)。如果子程序寫入 stdout 的資料量超過該限制,且輸出未被擷取,子程序會封鎖並等待管道緩衝區接受更多資料。這與 shell 中管道的行為相同。如果輸出不會被使用,請使用 { stdio: 'ignore' }
選項。
如果 env
在 options
物件中,則使用 options.env.PATH
環境變數執行命令查詢。否則,將使用 process.env.PATH
。如果設定 options.env
但沒有 PATH
,則在 Unix 上的查詢會在預設搜尋路徑 /usr/bin:/bin
上執行(請參閱作業系統手冊以取得 execvpe/execvp),在 Windows 上則使用目前程序的環境變數 PATH
。
在 Windows 上,環境變數不區分大小寫。Node.js 會依序對 env
鍵進行排序,並使用第一個不區分大小寫的匹配項。只會將第一個(依序序排序)項目傳遞給子程序。當將具有相同鍵的多個變體(例如 PATH
和 Path
)傳遞給 env
選項時,這可能會在 Windows 上造成問題。
child_process.spawn()
方法非同步地產生子程序,而不會阻擋 Node.js 事件迴圈。child_process.spawnSync()
函式以同步的方式提供等效功能,會阻擋事件迴圈,直到產生的程序退出或終止為止。
為方便起見,node:child_process
模組提供了一些 child_process.spawn()
和 child_process.spawnSync()
的同步和非同步替代方案。這些替代方案都是建立在 child_process.spawn()
或 child_process.spawnSync()
之上。
child_process.exec()
:產生一個 shell 並在該 shell 中執行一個命令,在完成時將stdout
和stderr
傳遞給回呼函式。child_process.execFile()
:類似於child_process.exec()
,但預設會直接產生命令,而不會先產生一個 shell。child_process.fork()
:產生新的 Node.js 程序,並呼叫指定模組,且建立 IPC 通訊管道,讓父程序與子程序間可以傳送訊息。child_process.execSync()
:child_process.exec()
的同步版本,會封鎖 Node.js 事件迴圈。child_process.execFileSync()
:child_process.execFile()
的同步版本,會封鎖 Node.js 事件迴圈。
對於某些使用案例,例如自動化 shell 腳本,同步對應項 可能會更方便。然而,在許多情況下,同步方法會因為在產生程序完成時暫停事件迴圈,而對效能造成重大影響。
非同步程序建立#
child_process.spawn()
、child_process.fork()
、child_process.exec()
和 child_process.execFile()
方法都遵循其他 Node.js API 常見的非同步程式設計模式。
每個方法都會傳回 ChildProcess
執行個體。這些物件實作 Node.js EventEmitter
API,讓父程序可以註冊監聽器函式,當子程序生命週期中發生特定事件時,就會呼叫這些函式。
child_process.exec()
和 child_process.execFile()
方法還允許指定一個選用的 callback
函式,當子程序終止時,就會呼叫這個函式。
在 Windows 上產生 .bat
和 .cmd
檔案#
child_process.exec()
和 child_process.execFile()
之間的區別,其重要性會根據平台而有所不同。在 Unix 類型的作業系統(Unix、Linux、macOS)上,child_process.execFile()
可能會更有效率,因為它預設不會產生 shell。然而,在 Windows 上,.bat
和 .cmd
檔案在沒有終端的狀況下無法自行執行,因此無法使用 child_process.execFile()
啟動。在 Windows 上執行時,可以使用 child_process.spawn()
搭配設定 shell
選項,使用 child_process.exec()
,或產生 cmd.exe
並將 .bat
或 .cmd
檔案作為引數傳遞(這是 shell
選項和 child_process.exec()
所執行的動作)來呼叫 .bat
和 .cmd
檔案。無論如何,如果指令碼檔名包含空白,則需要加上引號。
// On Windows Only...
const { spawn } = require('node:child_process');
const bat = spawn('cmd.exe', ['/c', 'my.bat']);
bat.stdout.on('data', (data) => {
console.log(data.toString());
});
bat.stderr.on('data', (data) => {
console.error(data.toString());
});
bat.on('exit', (code) => {
console.log(`Child exited with code ${code}`);
});
// OR...
const { exec, spawn } = require('node:child_process');
exec('my.bat', (err, stdout, stderr) => {
if (err) {
console.error(err);
return;
}
console.log(stdout);
});
// Script with spaces in the filename:
const bat = spawn('"my script.cmd"', ['a', 'b'], { shell: true });
// or:
exec('"my script.cmd" a b', (err, stdout, stderr) => {
// ...
});
child_process.exec(command[, options][, callback])
#
command
<字串> 要執行的指令,以空白分隔引數。options
<物件>cwd
<字串> | <URL> 子程序的目前工作目錄。預設值:process.cwd()
。env
<物件> 環境的鍵值對。預設值:process.env
。encoding
<字串> 預設值:'utf8'
shell
<字串> 用於執行命令的殼層。請參閱 殼層需求 和 預設 Windows 殼層。預設值: Unix 上為'/bin/sh'
,Windows 上為process.env.ComSpec
。signal
<中斷訊號> 允許使用中斷訊號中斷子程序。timeout
<數字> 預設值:0
maxBuffer
<數字> 允許在 stdout 或 stderr 上出現的資料最大位元組數。如果超過,子程序會終止,且所有輸出都會被截斷。請參閱maxBuffer
和 Unicode 的注意事項。預設值:1024 * 1024
。killSignal
<字串> | <整數> 預設值:'SIGTERM'
uid
<數字> 設定程序的使用者身分(請參閱setuid(2)
)。gid
<數字> 設定程序的群組身分 (請參閱setgid(2)
).windowsHide
<布林值> 隱藏在 Windows 系統上通常會建立的子程序主控台視窗。預設值:false
。
callback
<函式> 在程序終止時以輸出呼叫。- 傳回:<ChildProcess>
產生一個 shell,然後在該 shell 中執行 command
,並將任何產生的輸出暫存。傳遞給 exec 函式的 command
字串會直接由 shell 處理,而特殊字元 (根據 shell 而異) 需要適當地處理
const { exec } = require('node:child_process');
exec('"/path/to/test file/test.sh" arg1 arg2');
// Double quotes are used so that the space in the path is not interpreted as
// a delimiter of multiple arguments.
exec('echo "The \\$HOME variable is $HOME"');
// The $HOME variable is escaped in the first instance, but not in the second.
切勿將未整理的使用者輸入傳遞給此函式。任何包含 shell 元字元的輸入都可能用來觸發任意命令執行。
如果提供了 callback
函式,則會以引數 (error, stdout, stderr)
呼叫它。如果成功,error
會是 null
。如果發生錯誤,error
會是 Error
的執行個體。error.code
屬性會是程序的結束代碼。依慣例,任何結束代碼 (除了 0
) 都表示錯誤。error.signal
會是終止程序的訊號。
傳遞給回呼函式的 stdout
和 stderr
參數將包含子程序的 stdout 和 stderr 輸出。預設情況下,Node.js 會將輸出解碼為 UTF-8,並將字串傳遞給回呼函式。encoding
選項可用於指定用於解碼 stdout 和 stderr 輸出的字元編碼。如果 encoding
為 'buffer'
或無法辨識的字元編碼,則會將 Buffer
物件傳遞給回呼函式。
const { exec } = require('node:child_process');
exec('cat *.js missing_file | wc -l', (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
console.log(`stdout: ${stdout}`);
console.error(`stderr: ${stderr}`);
});
如果 timeout
大於 0
,如果子程序執行時間超過 timeout
毫秒,則父程序會傳送由 killSignal
屬性識別的訊號(預設為 'SIGTERM'
)。
與 exec(3)
POSIX 系統呼叫不同,child_process.exec()
不会取代現有程序,而是使用 shell 來執行命令。
如果此方法作為其 util.promisify()
版本呼叫,則會傳回一個 Promise
,以取得具有 stdout
和 stderr
屬性的 Object
。傳回的 ChildProcess
執行個體會作為 child
屬性附加到 Promise
。如果發生錯誤(包括導致退出碼不為 0 的任何錯誤),則會傳回一個遭拒絕的承諾,其中包含回呼函式中提供的相同 error
物件,但具有兩個額外的屬性 stdout
和 stderr
。
const util = require('node:util');
const exec = util.promisify(require('node:child_process').exec);
async function lsExample() {
const { stdout, stderr } = await exec('ls');
console.log('stdout:', stdout);
console.error('stderr:', stderr);
}
lsExample();
如果啟用 signal
選項,則對應的 AbortController
上呼叫 .abort()
類似於對子程序呼叫 .kill()
,但傳遞給回呼函式的錯誤將是 AbortError
const { exec } = require('node:child_process');
const controller = new AbortController();
const { signal } = controller;
const child = exec('grep ssh', { signal }, (error) => {
console.error(error); // an AbortError
});
controller.abort();
child_process.execFile(file[, args][, options][, callback])
#
file
<字串> 要執行的可執行檔名稱或路徑。args
<字串陣列> 字串引數清單。options
<物件>cwd
<字串> | <URL> 子程式的目前工作目錄。env
<物件> 環境的鍵值對。預設值:process.env
。encoding
<字串> 預設值:'utf8'
timeout
<數字> 預設值:0
maxBuffer
<數字> 允許在 stdout 或 stderr 上出現的資料最大位元組數。如果超過,子程序會終止,且所有輸出都會被截斷。請參閱maxBuffer
和 Unicode 的注意事項。預設值:1024 * 1024
。killSignal
<字串> | <整數> 預設值:'SIGTERM'
uid
<數字> 設定程序的使用者身分(請參閱setuid(2)
)。gid
<數字> 設定程序的群組身分 (請參閱setgid(2)
).windowsHide
<布林值> 隱藏在 Windows 系統上通常會建立的子程序主控台視窗。預設值:false
。windowsVerbatimArguments
<布林值> 在 Windows 上不會對引數進行任何引號或跳脫。在 Unix 上忽略。預設值:false
。shell
<布林值> | <字串> 如果為true
,會在 shell 內執行command
。在 Unix 上使用'/bin/sh'
,在 Windows 上使用process.env.ComSpec
。可以字串指定不同的 shell。請參閱 Shell 需求 和 預設 Windows shell。預設值:false
(沒有 shell)。signal
<中斷訊號> 允許使用中斷訊號中斷子程序。
callback
<函式> 在處理程序終止時呼叫,並傳入輸出。- 傳回:<ChildProcess>
child_process.execFile()
函式類似於 child_process.exec()
,但預設不會產生 shell。相反地,指定的可執行檔 file
會直接產生為新的處理程序,使其比 child_process.exec()
稍微有效率一點。
支援與 child_process.exec()
相同的選項。由於不會產生 shell,因此不支援 I/O 重新導向和檔案萬用字元等行為。
const { execFile } = require('node:child_process');
const child = execFile('node', ['--version'], (error, stdout, stderr) => {
if (error) {
throw error;
}
console.log(stdout);
});
傳遞給回呼函式的 stdout
和 stderr
參數將包含子程序的 stdout 和 stderr 輸出。預設情況下,Node.js 會將輸出解碼為 UTF-8,並將字串傳遞給回呼函式。encoding
選項可用於指定用於解碼 stdout 和 stderr 輸出的字元編碼。如果 encoding
為 'buffer'
或無法辨識的字元編碼,則會將 Buffer
物件傳遞給回呼函式。
如果此方法作為其 util.promisify()
版本呼叫,則會傳回一個 Promise
,以取得具有 stdout
和 stderr
屬性的 Object
。傳回的 ChildProcess
執行個體會作為 child
屬性附加到 Promise
。如果發生錯誤(包括導致退出碼不為 0 的任何錯誤),則會傳回一個遭拒絕的承諾,其中包含回呼函式中提供的相同 error
物件,但具有兩個額外的屬性 stdout
和 stderr
。
const util = require('node:util');
const execFile = util.promisify(require('node:child_process').execFile);
async function getVersion() {
const { stdout } = await execFile('node', ['--version']);
console.log(stdout);
}
getVersion();
如果啟用 shell
選項,請勿將未經 sanitizing 的使用者輸入傳遞給此函式。任何包含 shell 元字元的輸入都可能用於觸發任意命令執行。
如果啟用 signal
選項,則對應的 AbortController
上呼叫 .abort()
類似於對子程序呼叫 .kill()
,但傳遞給回呼函式的錯誤將是 AbortError
const { execFile } = require('node:child_process');
const controller = new AbortController();
const { signal } = controller;
const child = execFile('node', ['--version'], { signal }, (error) => {
console.error(error); // an AbortError
});
controller.abort();
child_process.fork(modulePath[, args][, options])
#
modulePath
<字串> | <URL> 要在子行程中執行的模組。args
<字串陣列> 字串引數清單。options
<物件>cwd
<字串> | <URL> 子程式的目前工作目錄。detached
<布林值> 準備子行程獨立於其父行程執行。特定行為取決於平台,請參閱options.detached
)。env
<物件> 環境的鍵值對。預設值:process.env
。execPath
<字串> 用於建立子行程的可執行檔。execArgv
<字串陣列> 傳遞給可執行檔的字串引數清單。預設值:process.execArgv
。gid
<數字> 設定程序的群組身分 (請參閱setgid(2)
).serialization
<字串> 指定用於在程序之間傳送訊息的序列化類型。可能的數值為'json'
和'advanced'
。有關更多詳細資訊,請參閱 進階序列化。預設值:'json'
。signal
<中斷訊號> 允許使用中斷訊號關閉子程序。killSignal
<字串> | <整數> 當產生程序因逾時或中斷訊號而終止時要使用的訊號值。預設值:'SIGTERM'
。silent
<布林值> 如果為true
,子程序的 stdin、stdout 和 stderr 會導管到父程序,否則會從父程序繼承,有關更多詳細資訊,請參閱child_process.spawn()
的stdio
的'pipe'
和'inherit'
選項。預設值:false
。stdio
<陣列> | <字串> 請參閱child_process.spawn()
的stdio
。提供此選項時,會覆寫silent
。如果使用陣列變體,它必須只包含一個值為'ipc'
的項目,否則會擲回錯誤。例如[0, 1, 2, 'ipc']
。uid
<數字> 設定程序的使用者身分(請參閱setuid(2)
)。windowsVerbatimArguments
<布林值> 在 Windows 上不會對引數進行任何引號或跳脫。在 Unix 上忽略。預設值:false
。timeout
<數字> 以毫秒為單位的程序執行時間上限。預設值:undefined
。
- 傳回:<ChildProcess>
child_process.fork()
方法是 child_process.spawn()
的特殊情況,專門用於產生新的 Node.js 程序。如同 child_process.spawn()
,會傳回 ChildProcess
物件。傳回的 ChildProcess
會有內建的額外通訊管道,讓訊息可以在父程序和子程序之間傳遞。有關詳細資訊,請參閱 subprocess.send()
。
請記住,產生的 Node.js 子程序獨立於父程序,但兩者之間建立的 IPC 通訊管道除外。每個程序都有自己的記憶體,以及自己的 V8 執行個體。由於需要額外的資源配置,因此不建議產生大量的 Node.js 子程序。
預設情況下,child_process.fork()
會使用父程序的 process.execPath
產生新的 Node.js 執行個體。options
物件中的 execPath
屬性允許使用替代的執行路徑。
使用自訂 execPath
啟動的 Node.js 程序會使用檔案描述符 (fd) 與父程序通訊,該檔案描述符在子程序上使用環境變數 NODE_CHANNEL_FD
識別。
與 fork(2)
POSIX 系統呼叫不同,child_process.fork()
不會複製目前的程序。
child_process.fork()
不支援 child_process.spawn()
中提供的 shell
選項,如果設定了該選項,將會略過。
如果啟用 signal
選項,則對應的 AbortController
上呼叫 .abort()
類似於對子程序呼叫 .kill()
,但傳遞給回呼函式的錯誤將是 AbortError
if (process.argv[2] === 'child') {
setTimeout(() => {
console.log(`Hello from ${process.argv[2]}!`);
}, 1_000);
} else {
const { fork } = require('node:child_process');
const controller = new AbortController();
const { signal } = controller;
const child = fork(__filename, ['child'], { signal });
child.on('error', (err) => {
// This will be called with err being an AbortError if the controller aborts
});
controller.abort(); // Stops the child process
}
child_process.spawn(command[, args][, options])
#
command
<字串> 要執行的指令。args
<字串陣列> 字串引數清單。options
<物件>cwd
<字串> | <URL> 子程式的目前工作目錄。env
<物件> 環境的鍵值對。預設值:process.env
。argv0
<字串> 明確設定傳送至子程序的argv[0]
值。如果未指定,則會設定為command
。stdio
<陣列> | <字串> 子程序的 stdio 設定 (請參閱options.stdio
)。detached
<布林值> 準備子行程獨立於其父行程執行。特定行為取決於平台,請參閱options.detached
)。uid
<數字> 設定程序的使用者身分(請參閱setuid(2)
)。gid
<數字> 設定程序的群組身分 (請參閱setgid(2)
).serialization
<字串> 指定用於在程序之間傳送訊息的序列化類型。可能的數值為'json'
和'advanced'
。有關更多詳細資訊,請參閱 進階序列化。預設值:'json'
。shell
<布林值> | <字串> 如果為true
,會在 shell 內執行command
。在 Unix 上使用'/bin/sh'
,在 Windows 上使用process.env.ComSpec
。可以字串指定不同的 shell。請參閱 Shell 需求 和 預設 Windows shell。預設值:false
(沒有 shell)。windowsVerbatimArguments
<布林值> 在 Windows 上不會對引數進行引號或跳脫處理。在 Unix 上會略過。當指定shell
且為 CMD 時,會自動將此設定為true
。預設值:false
。windowsHide
<布林值> 隱藏在 Windows 系統上通常會建立的子程序主控台視窗。預設值:false
。signal
<中斷訊號> 允許使用中斷訊號中斷子程序。timeout
<數字> 以毫秒為單位的程序執行時間上限。預設值:undefined
。killSignal
<字串> | <整數> 當產生程序因逾時或中斷訊號而終止時要使用的訊號值。預設值:'SIGTERM'
。
- 傳回:<ChildProcess>
child_process.spawn()
方法使用指定的 command
衍生新的程序,且命令列引數在 args
中。如果省略,args
預設為空陣列。
如果啟用 shell
選項,請勿將未經 sanitizing 的使用者輸入傳遞給此函式。任何包含 shell 元字元的輸入都可能用於觸發任意命令執行。
可以使用第三個引數指定其他選項,其預設值如下
const defaults = {
cwd: undefined,
env: process.env,
};
使用 cwd
指定衍生程序的工作目錄。如果未提供,預設值會繼承目前的目錄。如果提供了,但路徑不存在,子程序會發出 ENOENT
錯誤並立即結束。當指令不存在時也會發出 ENOENT
。
使用 env
指定新程序可見的環境變數,預設值為 process.env
。
env
中的 undefined
值會被略過。
執行 ls -lh /usr
、擷取 stdout
、stderr
和結束代碼的範例
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]
程式碼將與從父處理程序傳遞給 spawn
的 argv0
參數不符。改用 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
#
在 Windows 上,將 options.detached
設為 true
可以讓子處理程序在父處理程序結束後繼續執行。子處理程序將有自己的主控台視窗。一旦為子處理程序啟用,就無法停用。
在非 Windows 平台上,如果將 options.detached
設為 true
,子處理程序將成為新的處理程序群組和工作階段的負責人。無論子處理程序是否分離,它們都可以在父處理程序結束後繼續執行。請參閱 setsid(2)
以取得更多資訊。
預設情況下,父處理程序會等待分離的子處理程序結束。若要防止父處理程序等待指定的 subprocess
結束,請使用 subprocess.unref()
方法。這樣做會導致父處理程序的事件迴圈不會將子處理程序包含在其參考計數中,讓父處理程序可以獨立於子處理程序結束,除非子處理程序和父處理程序之間建立了已建立的 IPC 通道。
當使用 detached
選項啟動長時間執行的處理程序時,除非提供未連接到父處理程序的 stdio
設定,否則處理程序在父處理程序結束後不會繼續在背景中執行。如果繼承父處理程序的 stdio
,子處理程序將保持連接到控制終端。
長時間執行的處理程序範例,透過分離並忽略其父 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
#
options.stdio
選項用於設定在父程序和子程序之間建立的管線。預設情況下,子程序的 stdin、stdout 和 stderr 會重新導向到 subprocess.stdin
、subprocess.stdout
和 subprocess.stderr
串流上的對應 ChildProcess
物件。這等於將 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。fd 0、1 和 2 分別對應到 stdin、stdout 和 stderr。可以指定其他 fd 來在父程序和子程序之間建立其他管線。值為下列其中一個
-
'pipe'
:在子程序和父程序之間建立管道。管道的父端會以subprocess.stdio[fd]
的屬性形式在child_process
物件上顯示給父端。為 fd 0、1 和 2 建立的管道也可以分別以subprocess.stdin
、subprocess.stdout
和subprocess.stderr
的形式使用。這些並非實際的 Unix 管道,因此子程序無法透過其描述符檔案使用它們,例如/dev/fd/2
或/dev/stdout
。 -
'overlapped'
:與'pipe'
相同,但會在控制碼上設定FILE_FLAG_OVERLAPPED
旗標。這是子程序的 stdio 控制碼上重疊 I/O 所必需的。請參閱 文件 以取得更多詳細資訊。這在非 Windows 系統上與'pipe'
完全相同。 -
'ipc'
:建立 IPC 通道,以便在父端和子端之間傳遞訊息/檔案描述符。ChildProcess
最多可以有一個 IPC stdio 檔案描述符。設定這個選項會啟用subprocess.send()
方法。如果子端是 Node.js 程序,則 IPC 通道的存在會啟用process.send()
和process.disconnect()
方法,以及子端中的'disconnect'
和'message'
事件。不支援透過
process.send()
以外的方式存取 IPC 通道 fd,或將 IPC 通道與非 Node.js 執行個體的子程序一起使用。 -
'ignore'
:指示 Node.js 忽略子端中的 fd。雖然 Node.js 始終會為其衍生的程序開啟 fd 0、1 和 2,但將 fd 設定為'ignore'
會導致 Node.js 開啟/dev/null
並將其附加到子端的 fd。 -
'inherit'
:傳遞對應的 stdio 串流至/從父程序。在前三個位置,這等於分別為process.stdin
、process.stdout
和process.stderr
。在任何其他位置,則等於'ignore'
。 -
<Stream> 物件:共用可讀或可寫的串流,該串流指向 tty、檔案、socket 或與子程序的管道。串流的底層檔案描述符會在子程序中複製到對應於
stdio
陣列中索引的 fd。串流必須有底層描述符(檔案串流直到發生'open'
事件才會啟動)。 -
正整數:整數值會被解釋為在父程序中開啟的檔案描述符。它會與子程序共用,類似於 <Stream> 物件可以共用的方式。在 Windows 上不支援傳遞 socket。
-
null
、undefined
:使用預設值。對於 stdio fd 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 通道而讓程序保持開啟狀態。
同步程序建立#
child_process.spawnSync()
、child_process.execSync()
和 child_process.execFileSync()
方法是同步的,它們會封鎖 Node.js 事件迴圈,暫停執行任何額外的程式碼,直到衍生的程序退出。
像這樣的封鎖呼叫對於簡化一般用途的指令碼任務以及簡化在啟動時載入/處理應用程式組態非常有用。
child_process.execFileSync(file[, args][, options])
#
file
<字串> 要執行的可執行檔名稱或路徑。args
<字串陣列> 字串引數清單。options
<物件>cwd
<字串> | <URL> 子程式的目前工作目錄。input
<字串> | <Buffer> | <TypedArray> | <DataView> 將傳遞給衍生程序的 stdin 的值。如果將stdio[0]
設定為'pipe'
,提供此值將會覆寫stdio[0]
。stdio
<字串> | <陣列> 子程序的 stdio 組態。除非指定stdio
,否則stderr
預設會輸出到父程序的 stderr。預設值:'pipe'
。env
<物件> 環境的鍵值對。預設值:process.env
。uid
<數字> 設定程序的使用者身分(請參閱setuid(2)
)。gid
<數字> 設定程序的群組身分 (請參閱setgid(2)
).timeout
<數字> 以毫秒為單位的程序執行時間上限。預設值:undefined
。killSignal
<字串> | <整數> 當衍生程序將被終止時要使用的訊號值。預設值:'SIGTERM'
。maxBuffer
<數字> stdout 或 stderr 上允許的最大資料位元組數。如果超過,子程序會被終止。請參閱maxBuffer
和 Unicode 的注意事項。預設值:1024 * 1024
。encoding
<字串> 用於所有 stdio 輸入和輸出的編碼。預設值:'buffer'
。windowsHide
<布林值> 隱藏在 Windows 系統上通常會建立的子程序主控台視窗。預設值:false
。shell
<布林值> | <字串> 如果為true
,會在 shell 內執行command
。在 Unix 上使用'/bin/sh'
,在 Windows 上使用process.env.ComSpec
。可以字串指定不同的 shell。請參閱 Shell 需求 和 預設 Windows shell。預設值:false
(沒有 shell)。
- 傳回:<Buffer> | <字串> 來自命令的 stdout。
child_process.execFileSync()
方法通常與 child_process.execFile()
相同,但例外情況是該方法不會在子程序完全關閉之前傳回。當遇到逾時且傳送 killSignal
時,該方法不會在程序完全結束之前傳回。
如果子程序攔截並處理 SIGTERM
訊號且未結束,父程序仍會等到子程序結束。
如果程序逾時或有非零結束代碼,此方法會擲回 Error
,其中會包含基礎 child_process.spawnSync()
的完整結果。
如果啟用 shell
選項,請勿將未經 sanitizing 的使用者輸入傳遞給此函式。任何包含 shell 元字元的輸入都可能用於觸發任意命令執行。
child_process.execSync(command[, options])
#
command
<字串> 要執行的指令。options
<物件>cwd
<字串> | <URL> 子程式的目前工作目錄。input
<字串> | <Buffer> | <TypedArray> | <DataView> 將傳遞給衍生程序的 stdin 的值。如果將stdio[0]
設定為'pipe'
,提供此值將會覆寫stdio[0]
。stdio
<字串> | <陣列> 子程序的 stdio 組態。除非指定stdio
,否則stderr
預設會輸出到父程序的 stderr。預設值:'pipe'
。env
<物件> 環境的鍵值對。預設值:process.env
。shell
<字串> 用於執行命令的殼層。請參閱 殼層需求 和 預設 Windows 殼層。預設值: Unix 上為'/bin/sh'
,Windows 上為process.env.ComSpec
。uid
<number> 設定程序的使用者身分。(請參閱setuid(2)
).gid
<number> 設定程序的群組身分。(請參閱setgid(2)
).timeout
<數字> 以毫秒為單位的程序執行時間上限。預設值:undefined
。killSignal
<字串> | <整數> 當衍生程序將被終止時要使用的訊號值。預設值:'SIGTERM'
。maxBuffer
<數字> 允許在 stdout 或 stderr 上出現的資料最大位元組數。如果超過,子程序會終止,且所有輸出都會被截斷。請參閱maxBuffer
和 Unicode 的注意事項。預設值:1024 * 1024
。encoding
<字串> 用於所有 stdio 輸入和輸出的編碼。預設值:'buffer'
。windowsHide
<布林值> 隱藏在 Windows 系統上通常會建立的子程序主控台視窗。預設值:false
。
- 傳回:<Buffer> | <字串> 來自命令的 stdout。
child_process.execSync()
方法通常與 child_process.exec()
相同,但例外情況是該方法不會在子程序完全關閉之前傳回。當遇到逾時且傳送 killSignal
時,該方法不會在程序完全結束之前傳回。如果子程序攔截並處理 SIGTERM
訊號且未結束,父程序會等到子程序結束。
如果程序逾時或有非零結束代碼,此方法會擲回。Error
物件會包含 child_process.spawnSync()
的完整結果。
切勿將未整理的使用者輸入傳遞給此函式。任何包含 shell 元字元的輸入都可能用來觸發任意命令執行。
child_process.spawnSync(command[, args][, options])
#
command
<字串> 要執行的指令。args
<字串陣列> 字串引數清單。options
<物件>cwd
<字串> | <URL> 子程式的目前工作目錄。input
<字串> | <Buffer> | <TypedArray> | <DataView> 將傳遞給衍生程序的 stdin 的值。如果將stdio[0]
設定為'pipe'
,提供此值將會覆寫stdio[0]
。argv0
<字串> 明確設定傳送至子程序的argv[0]
值。如果未指定,則會設定為command
。stdio
<string> | <Array> 子程序的 stdio 組態。預設值:'pipe'
。env
<物件> 環境的鍵值對。預設值:process.env
。uid
<數字> 設定程序的使用者身分(請參閱setuid(2)
)。gid
<數字> 設定程序的群組身分 (請參閱setgid(2)
).timeout
<數字> 以毫秒為單位的程序執行時間上限。預設值:undefined
。killSignal
<字串> | <整數> 當衍生程序將被終止時要使用的訊號值。預設值:'SIGTERM'
。maxBuffer
<數字> 允許在 stdout 或 stderr 上出現的資料最大位元組數。如果超過,子程序會終止,且所有輸出都會被截斷。請參閱maxBuffer
和 Unicode 的注意事項。預設值:1024 * 1024
。encoding
<字串> 用於所有 stdio 輸入和輸出的編碼。預設值:'buffer'
。shell
<布林值> | <字串> 如果為true
,會在 shell 內執行command
。在 Unix 上使用'/bin/sh'
,在 Windows 上使用process.env.ComSpec
。可以字串指定不同的 shell。請參閱 Shell 需求 和 預設 Windows shell。預設值:false
(沒有 shell)。windowsVerbatimArguments
<布林值> 在 Windows 上不會對引數進行引號或跳脫處理。在 Unix 上會略過。當指定shell
且為 CMD 時,會自動將此設定為true
。預設值:false
。windowsHide
<布林值> 隱藏在 Windows 系統上通常會建立的子程序主控台視窗。預設值:false
。
- 傳回:<Object>
child_process.spawnSync()
方法通常與 child_process.spawn()
相同,但例外情況是,此函式不會在子程序完全關閉之前傳回。當遇到逾時且傳送 killSignal
時,此方法不會在程序完全結束之前傳回。如果程序攔截並處理 SIGTERM
訊號且未結束,則父程序會等到子程序結束。
如果啟用 shell
選項,請勿將未經 sanitizing 的使用者輸入傳遞給此函式。任何包含 shell 元字元的輸入都可能用於觸發任意命令執行。
類別:ChildProcess
#
ChildProcess
的執行個體代表已產生的子處理程序。
ChildProcess
的執行個體並非用於直接建立。請改用 child_process.spawn()
、child_process.exec()
、child_process.execFile()
或 child_process.fork()
方法建立 ChildProcess
的執行個體。
事件:'close'
#
'close'
事件會在處理程序結束且子處理程序的 stdio 串流關閉後發出。這與 'exit'
事件不同,因為多個處理程序可能會共用相同的 stdio 串流。'close'
事件會在 'exit'
或子執行緒產生錯誤時發出的 'error'
之後發出。
const { spawn } = require('node:child_process');
const ls = spawn('ls', ['-lh', '/usr']);
ls.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
ls.on('close', (code) => {
console.log(`child process close all stdio with code ${code}`);
});
ls.on('exit', (code) => {
console.log(`child process exited with code ${code}`);
});
事件:'disconnect'
#
在父程序中呼叫 subprocess.disconnect()
方法或在子程序中呼叫 process.disconnect()
之後會發出 'disconnect'
事件。中斷連線後,將無法再傳送或接收訊息,且 subprocess.connected
屬性為 false
。
事件:'error'
#
err
<Error> 錯誤。
在以下情況下會發出 'error'
事件:
- 無法產生程序。
- 無法終止程序。
- 傳送訊息至子程序失敗。
- 子程序透過
signal
選項中斷。
在發生錯誤後,'exit'
事件可能會觸發,也可能不會。在同時監聽 'exit'
和 'error'
事件時,請注意不要意外地多次呼叫處理常式函數。
另請參閱 subprocess.kill()
和 subprocess.send()
。
事件:'exit'
#
在子程序結束後會發出 'exit'
事件。如果程序已結束,code
為程序的最終結束代碼,否則為 null
。如果程序因收到訊號而終止,signal
為訊號的字串名稱,否則為 null
。這兩個值其中一個必定為非 null
。
觸發 'exit'
事件時,子程序的 stdio 串流可能仍為開啟狀態。
Node.js 會為 SIGINT
和 SIGTERM
建立訊號處理常式,而 Node.js 程序並不會因為收到這些訊號而立即終止。相反地,Node.js 會執行一系列清理動作,然後重新引發已處理的訊號。
請參閱 waitpid(2)
。
事件:'message'
#
message
<Object> 已剖析的 JSON 物件或原始值。sendHandle
<Handle>net.Socket
或net.Server
物件,或未定義。
當子程序使用 process.send()
傳送訊息時,會觸發 'message'
事件。
訊息會經過序列化和剖析。產生的訊息可能與原本傳送的訊息不同。
如果在產生子程序時將 serialization
選項設定為 'advanced'
,則 message
參數可以包含 JSON 無法表示的資料。請參閱 進階序列化 以取得更多詳細資訊。
事件:'spawn'
#
一旦子程序成功產生,就會發出 'spawn'
事件。如果子程序未成功產生,則不會發出 'spawn'
事件,而是會發出 'error'
事件。
如果發出,'spawn'
事件會在所有其他事件之前,以及透過 stdout
或 stderr
收到任何資料之前發出。
無論在產生的程序 內部 是否發生錯誤,'spawn'
事件都會觸發。例如,如果 bash some-command
成功產生,則 'spawn'
事件會觸發,儘管 bash
可能無法產生 some-command
。這個注意事項也適用於使用 { shell: true }
的情況。
subprocess.channel
#
- <Object>代表 IPC 通道至子程式的管線。
subprocess.channel
屬性是對子程式 IPC 通道的參照。如果沒有 IPC 通道,此屬性為 undefined
。
subprocess.channel.ref()
#
如果先前已呼叫 .unref()
,此方法會讓 IPC 通道保持父程式事件迴圈執行。
subprocess.channel.unref()
#
此方法會讓 IPC 通道不保持父程式事件迴圈執行,並讓它在通道開啟時也能結束。
subprocess.connected
#
- <boolean>在呼叫
subprocess.disconnect()
之後設為false
。
subprocess.connected
屬性指出是否仍可以從子程式傳送和接收訊息。當 subprocess.connected
為 false
時,便無法再傳送或接收訊息。
subprocess.disconnect()
#
關閉父程式和子程式之間的 IPC 通道,讓子程式在沒有其他連線讓它保持運作的情況下正常結束。在呼叫此方法後,父程式和子程式 (分別) 中的 subprocess.connected
和 process.connected
屬性將設為 false
,且將無法再在程式之間傳遞訊息。
當沒有訊息正在接收的過程中,將會發出 'disconnect'
事件。這通常會在呼叫 subprocess.disconnect()
之後立即觸發。
當子程序是 Node.js 執行個體(例如使用 child_process.fork()
產生)時,可以在子程序中呼叫 process.disconnect()
方法,以關閉 IPC 通道。
subprocess.exitCode
#
subprocess.exitCode
屬性表示子程序的結束代碼。如果子程序仍然在執行中,該欄位將會是 null
。
subprocess.kill([signal])
#
subprocess.kill()
方法會將訊號傳送給子程序。如果沒有提供參數,程序將會傳送 'SIGTERM'
訊號。請參閱 signal(7)
以取得可用訊號的清單。如果 kill(2)
成功,此函式會傳回 true
,否則傳回 false
。
const { spawn } = require('node:child_process');
const grep = spawn('grep', ['ssh']);
grep.on('close', (code, signal) => {
console.log(
`child process terminated due to receipt of signal ${signal}`);
});
// Send SIGHUP to process.
grep.kill('SIGHUP');
如果無法傳遞訊號,ChildProcess
物件可能會發出 'error'
事件。將訊號傳送給已結束的子程序並非錯誤,但可能會產生無法預見的後果。特別是,如果程序識別碼 (PID) 已重新指定給另一個程序,訊號將會傳遞給該程序,這可能會產生意外的結果。
雖然此函數稱為 kill
,但傳送至子程式的訊號可能並未實際終止該程式。
請參閱 kill(2)
作為參考。
在 POSIX 訊號不存在的 Windows 上,signal
參數將會被忽略,且程式會被強制且突然地終止(類似於 'SIGKILL'
)。請參閱 訊號事件 以取得更多詳細資料。
在 Linux 上,嘗試終止其父程式時,子程式的子程式不會被終止。這很可能會在 shell 中執行新程式或使用 ChildProcess
的 shell
選項時發生。
'use strict';
const { spawn } = require('node:child_process');
const subprocess = spawn(
'sh',
[
'-c',
`node -e "setInterval(() => {
console.log(process.pid, 'is alive')
}, 500);"`,
], {
stdio: ['inherit', 'inherit', 'inherit'],
},
);
setTimeout(() => {
subprocess.kill(); // Does not terminate the Node.js process in the shell.
}, 2000);
subprocess[Symbol.dispose]()
#
呼叫 subprocess.kill()
並指定 'SIGTERM'
。
subprocess.killed
#
- <boolean> 在使用
subprocess.kill()
成功向子程式傳送訊號後,設為true
。
subprocess.killed
屬性表示子程式是否已成功從 subprocess.kill()
收到訊號。killed
屬性並不表示子程式已終止。
subprocess.pid
#
傳回子程序的程序識別碼 (PID)。如果子程序由於錯誤而無法產生,則值為 undefined
,並會發出 error
。
const { spawn } = require('node:child_process');
const grep = spawn('grep', ['ssh']);
console.log(`Spawned child pid: ${grep.pid}`);
grep.stdin.end();
subprocess.ref()
#
在呼叫 subprocess.unref()
之後呼叫 subprocess.ref()
,將會復原已移除的子程序參考計數,強制父程序等待子程序結束後再結束自己。
const { spawn } = require('node:child_process');
const subprocess = spawn(process.argv[0], ['child_program.js'], {
detached: true,
stdio: 'ignore',
});
subprocess.unref();
subprocess.ref();
subprocess.send(message[, sendHandle[, options]][, callback])
#
message
<Object>sendHandle
<Handle>options
<Object> 如果有提供options
參數,則此為用於參數化傳送特定類型控制代碼的物件。options
支援下列屬性keepOpen
<boolean> 傳遞net.Socket
執行個體時可使用的值。當true
時,會在傳送程序中保持 socket 開啟。預設值:false
。
callback
<Function>- 傳回:<布林值>
當父程序和子程序之間已建立 IPC 通道(例如,使用 child_process.fork()
時),可使用 subprocess.send()
方法傳送訊息至子程序。當子程序為 Node.js 執行個體時,可透過 'message'
事件接收這些訊息。
訊息會經過序列化和剖析。產生的訊息可能與原本傳送的訊息不同。
例如,在父程序指令碼中
const cp = require('node:child_process');
const n = cp.fork(`${__dirname}/sub.js`);
n.on('message', (m) => {
console.log('PARENT got message:', m);
});
// Causes the child to print: CHILD got message: { hello: 'world' }
n.send({ hello: 'world' });
然後子程序指令碼 'sub.js'
可能會像這樣
process.on('message', (m) => {
console.log('CHILD got message:', m);
});
// Causes the parent to print: PARENT got message: { foo: 'bar', baz: null }
process.send({ foo: 'bar', baz: NaN });
子程序 Node.js 會有自己的 process.send()
方法,讓子程序可以將訊息傳送回父程序。
傳送 {cmd: 'NODE_foo'}
訊息時,有一個特殊情況。在 cmd
屬性中包含 NODE_
前綴的訊息,是保留給 Node.js 核心使用的,不會在子程序的 'message'
事件中發出。這些訊息會使用 'internalMessage'
事件發出,並由 Node.js 內部使用。應用程式應避免使用此類訊息,或偵聽 'internalMessage'
事件,因為它可能會在未通知的情況下變更。
可以傳遞給 subprocess.send()
的選用 sendHandle
參數,是用於將 TCP 伺服器或 socket 物件傳遞給子程序。子程序會將物件接收為註冊在 'message'
事件上的 callback 函式的第二個參數。在 socket 中接收並緩衝的任何資料,都不會傳送給子程序。
選用的 callback
是在傳送訊息後,但在子程序可能尚未接收訊息之前呼叫的函式。此函式會呼叫單一參數:成功時為 null
,失敗時為 Error
物件。
如果未提供 callback
函式,而且無法傳送訊息,ChildProcess
物件會發出 'error'
事件。例如,當子程序已經結束時,就會發生這種情況。
如果頻道已關閉,或未傳送訊息的積壓量超過不建議再傳送更多訊息的臨界值,subprocess.send()
會傳回 false
。否則,此方法會傳回 true
。callback
函式可以用於實作流程控制。
範例:傳送伺服器物件#
sendHandle
參數可用於將 TCP 伺服器物件的控制代碼傳遞給子程序,如下例所示
const subprocess = require('node:child_process').fork('subprocess.js');
// Open up the server object and send the handle.
const server = require('node:net').createServer();
server.on('connection', (socket) => {
socket.end('handled by parent');
});
server.listen(1337, () => {
subprocess.send('server', server);
});
然後子程序會收到伺服器物件,如下所示
process.on('message', (m, server) => {
if (m === 'server') {
server.on('connection', (socket) => {
socket.end('handled by child');
});
}
});
一旦伺服器在父程序和子程序之間共用,某些連線可以由父程序處理,而某些則由子程序處理。
雖然上述範例使用 node:net
模組建立的伺服器,但 node:dgram
模組伺服器使用完全相同的工作流程,但例外情況是監聽 'message'
事件,而不是 'connection'
,並使用 server.bind()
而不是 server.listen()
。不過,這僅支援 Unix 平台。
範例:傳送 socket 物件#
類似地,sendHandler
參數可用於將 socket 的控制代碼傳遞給子程序。下列範例產生兩個子程序,每個子程序都處理具有「一般」或「特殊」優先順序的連線
const { fork } = require('node:child_process');
const normal = fork('subprocess.js', ['normal']);
const special = fork('subprocess.js', ['special']);
// Open up the server and send sockets to child. Use pauseOnConnect to prevent
// the sockets from being read before they are sent to the child process.
const server = require('node:net').createServer({ pauseOnConnect: true });
server.on('connection', (socket) => {
// If this is special priority...
if (socket.remoteAddress === '74.125.127.100') {
special.send('socket', socket);
return;
}
// This is normal priority.
normal.send('socket', socket);
});
server.listen(1337);
subprocess.js
會將 socket 控制代碼接收為傳遞給事件回呼函式的第二個參數
process.on('message', (m, socket) => {
if (m === 'socket') {
if (socket) {
// Check that the client socket exists.
// It is possible for the socket to be closed between the time it is
// sent and the time it is received in the child process.
socket.end(`Request handled with ${process.argv[2]} priority`);
}
}
});
不要對已傳遞給子程序的 socket 使用 .maxConnections
。父程序無法追蹤 socket 何時會毀損。
子程序中的任何 'message'
處理常式都應驗證 socket
是否存在,因為在將連線傳送給子程序的過程中,連線可能已關閉。
subprocess.signalCode
#
subprocess.signalCode
屬性表示子程序收到的訊號(如果有),否則為 null
。
subprocess.spawnargs
#
subprocess.spawnargs
屬性表示用於啟動子程序的命令列引數的完整清單。
subprocess.spawnfile
#
subprocess.spawnfile
屬性表示啟動的子程序的可執行檔檔名。
對於 child_process.fork()
,其值將等於 process.execPath
。對於 child_process.spawn()
,其值將是可執行檔的檔名。對於 child_process.exec()
,其值將是啟動子程序的殼層的名稱。
subprocess.stderr
#
表示子程序的 stderr
的 可讀取串流
。
如果子程序是用將 stdio[2]
設定為 'pipe'
以外的任何值來產生,則此值將為 null
。
subprocess.stderr
是 subprocess.stdio[2]
的別名。兩個屬性都會參考相同的值。
如果無法成功產生子程序,則 subprocess.stderr
屬性可能會為 null
或 undefined
。
subprocess.stdin
#
表示子程序的 stdin
的 可寫入串流
。
如果子程序等待讀取其所有輸入,則子程序將不會繼續,直到此串流透過 end()
關閉。
如果子程序已使用設定為非 'pipe'
的 stdio[0]
產生,則此值將會是 null
。
subprocess.stdin
是 subprocess.stdio[0]
的別名。兩個屬性都會參照相同的值。
如果無法成功產生子程序,則 subprocess.stdin
屬性可以是 null
或 undefined
。
subprocess.stdio
#
傳遞至子程序的管線稀疏陣列,對應傳遞至 child_process.spawn()
的 stdio
選項中的位置,已設定為 'pipe'
值。subprocess.stdio[0]
、subprocess.stdio[1]
和 subprocess.stdio[2]
也可用作 subprocess.stdin
、subprocess.stdout
和 subprocess.stderr
。
在以下範例中,只有子程序的 fd 1
(stdout) 設定為管線,因此只有父程序的 subprocess.stdio[1]
是串流,陣列中的所有其他值都是 null
。
const assert = require('node:assert');
const fs = require('node:fs');
const child_process = require('node:child_process');
const subprocess = child_process.spawn('ls', {
stdio: [
0, // Use parent's stdin for child.
'pipe', // Pipe child's stdout to parent.
fs.openSync('err.out', 'w'), // Direct child's stderr to a file.
],
});
assert.strictEqual(subprocess.stdio[0], null);
assert.strictEqual(subprocess.stdio[0], subprocess.stdin);
assert(subprocess.stdout);
assert.strictEqual(subprocess.stdio[1], subprocess.stdout);
assert.strictEqual(subprocess.stdio[2], null);
assert.strictEqual(subprocess.stdio[2], subprocess.stderr);
如果無法成功產生子程序,則 subprocess.stdio
屬性可以是 undefined
。
subprocess.stdout
#
代表子程序 stdout
的 可讀取串流
。
如果子程序已使用設定為非 'pipe'
的 stdio[1]
產生,則此值將會是 null
。
subprocess.stdout
是 subprocess.stdio[1]
的別名。兩個屬性都會參照相同的值。
const { spawn } = require('node:child_process');
const subprocess = spawn('ls');
subprocess.stdout.on('data', (data) => {
console.log(`Received chunk ${data}`);
});
如果無法成功產生子程序,則 subprocess.stdout
屬性可以是 null
或 undefined
。
subprocess.unref()
#
預設情況下,父處理程序會等待分離的子處理程序結束。若要防止父處理程序等待指定的 subprocess
結束,請使用 subprocess.unref()
方法。這樣做會導致父處理程序的事件迴圈不會將子處理程序包含在其參考計數中,讓父處理程序可以獨立於子處理程序結束,除非子處理程序和父處理程序之間建立了已建立的 IPC 通道。
const { spawn } = require('node:child_process');
const subprocess = spawn(process.argv[0], ['child_program.js'], {
detached: true,
stdio: 'ignore',
});
subprocess.unref();
maxBuffer
和 Unicode#
maxBuffer
選項指定允許在 stdout
或 stderr
上的最大位元組數。如果超過此值,則會終止子程序。這會影響包含多位元組字元編碼(例如 UTF-8 或 UTF-16)的輸出。例如,console.log('中文測試')
會將 13 個 UTF-8 編碼的位元組傳送至 stdout
,即使只有 4 個字元。
Shell 需求#
Shell 應了解 -c
參數。如果 Shell 為 'cmd.exe'
,它應了解 /d /s /c
參數,且命令列剖析應相容。
預設 Windows Shell#
儘管 Microsoft 指定 %COMSPEC%
必須在根目錄環境中包含 'cmd.exe'
的路徑,但子程序並不總是受限於相同的需求。因此,在 child_process
函式中,如果無法使用 process.env.ComSpec
,則會使用 'cmd.exe'
作為備用。
進階序列化#
子程序支援基於 node:v8
模組的序列化 API 的 IPC 序列化機制,該機制基於 HTML 結構化複製演算法。這通常更強大,並支援更多內建 JavaScript 物件類型,例如 BigInt
、Map
和 Set
、ArrayBuffer
和 TypedArray
、Buffer
、Error
、RegExp
等。
不過,此格式並非 JSON 的完整超集,例如,設定在內建型別物件上的屬性將不會透過序列化步驟傳遞。此外,效能可能無法等同於 JSON,具體取決於傳遞資料的結構。因此,此功能需要在呼叫 child_process.spawn()
或 child_process.fork()
時,設定 serialization
選項為 'advanced'
才能啟用。