1. 程式人生 > 其它 >NodeJs 子程序child_process

NodeJs 子程序child_process

官方文件

child_process 模組提供了以與 popen(3) 類似但不完全相同的方式衍生子程序的能力。 此功能主要由 child_process.spawn() 函式提供:

1. spawn

child_process.spawn()方法使用給定的commandargs中的命令列引數衍生新程序。 如果省略,args預設為空陣列。

如果啟用了shell選項,則請勿將未經處理的使用者輸入傳遞給此函式。 任何包含 shell 元字元的輸入都可用於觸發任意命令執行。

  • command<string>要執行的命令。

  • args<string[]>字串引數列表。

  • options

    <Object>

    • cwd<string>|<URL>子程序的當前工作目錄。
    • env<Object>環境變數鍵值對。預設值:process.env
    • argv0<string>顯式設定傳送給子程序的argv[0]的值。 如果未指定,這將設定為command
    • stdio<Array>|<string>子程序的標準輸入輸出配置(參見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>允許使用中止訊號中止子程序。
    • timeout<number>允許程序執行的最長時間(以毫秒為單位)。預設值:undefined
    • killSignal<string>|<integer>當衍生的程序將被超時或中止訊號殺死時要使用的訊號值。預設值:'SIGTERM'
  • 返回:<ChildProcess>

對於其它的方法,引數類似

 1 const ps = child.spawn('ps', ['ax']);
 2 const grep = child.spawn('grep', ['ssh']);
 3 
 4 ps.stdout.on('data', (data) => {
 5     grep.stdin.write(data);
 6 });
 7 
 8 ps.stderr.on('data', (data) => {
 9     console.error(`ps stderr: ${data}`);
10 });
11 
12 ps.on('close', (code) => {
13     if (code !== 0) {
14         console.log(`ps process exited with code ${code}`);
15     }
16     grep.stdin.end();
17 });
18 
19 grep.stdout.on('data', (data) => {
20     console.log(data.toString());
21 });
22 
23 grep.stderr.on('data', (data) => {
24     console.error(`grep stderr: ${data}`);
25 });
26 
27 grep.on('close', (code) => {
28     if (code !== 0) {
29         console.log(`grep process exited with code ${code}`);
30     }
31 });

2. exec

和spawn功能類似,用於另開程序啟動shell命令。

child_process.exec()不替換現有程序,而是使用 shell 來執行命令。

舉例:讓其用ts-node直接執行typescript程式碼

1 import * as child from 'child_process';
2 
3 child.exec('ts-node child.ts 1', ((error, stdout, stderr) => {
4     if (error) {
5         console.error(error);
6         return;
7     }
8     console.log(stdout);
9 }));

3. execfile

和exec類似,不同之處在於它預設不衍生 shell。 而是,指定的可執行檔案file直接作為新程序衍生,使其比child_process.exec()略有效率。

有args引數可以傳型別為Array[string]的引數

1 import * as child from 'child_process';
2 
3 child.execFile('ts-node', ['child.ts'], ((error, stdout, stderr) => {
4     if (error) {
5         console.error(error);
6         return;
7     }
8     console.log(stdout);
9 }));

4. fork

用於另開程序執行javascript指令碼,直接傳js路徑

1 import * as child from 'child_process';
2 
3 const c1 = child.fork('child.js', ['2'], {
4     silent: false,
5 });
6 
7 const c2 = child.fork('child.js',['3'], {
8     silent: false,
9 });

5. sync

每個方法都有對應的sync版本,nodejs執行時會阻塞直至子程序完全退出

6. 事件

'close'事件

  • code<number>如果子程序自己退出,則為退出碼。
  • signal<string>終止子程序的訊號。

在程序已結束並且子程序的標準輸入輸出流已關閉之後,則觸發'close'事件。 這與'exit'事件不同,因為多個程序可能共享相同的標準輸入輸出流。'close'事件將始終在'exit''error'(如果子程序衍生失敗)已經觸發之後觸發。

const { spawn } = require('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'事件

'error'事件在以下情況下觸發:

  1. 無法衍生該程序,或
  2. 程序無法終止,或
  3. 向子程序傳送訊息失敗。

發生錯誤後,'exit'事件可能會也可能不會觸發。 在監聽'exit''error'事件時,防止多次意外呼叫控制代碼函式。

另見subprocess.kill()subprocess.send()

'exit'事件

  • code<number>如果子程序自己退出,則為退出碼。
  • signal<string>終止子程序的訊號。

'exit'事件在子程序結束後觸發。 如果程序退出,則code為最終的程序退出碼,否則為null。 如果程序因收到訊號而終止,則signal是訊號的字串名稱,否則為null。 兩者之一將始終是非null

'exit'事件被觸發時,子程序標準輸入輸出流可能仍處於開啟狀態。

Node.js 為SIGINTSIGTERM建立訊號控制代碼,且 Node.js 程序不會因為收到這些訊號而立即終止。 而是,Node.js 將執行一系列清理操作,然後重新觸發已處理的訊號。

參見waitpid(2)

'message'事件

當子程序使用process.send()傳送訊息時,則觸發'message'事件。

訊息經過序列化和解析。 結果訊息可能與最初發送的訊息不同。

如果在衍生子程序時將serialization選項設定為'advanced',則message引數可以包含 JSON 無法表示的資料。 有關更多詳細資訊,請參閱高階序列化

'spawn'事件

一旦子程序衍生成功,則會觸發'spawn'事件。 如果子程序沒有衍生成功,則不會觸發'spawn'事件,而是觸發'error'事件。

如果觸發,則'spawn'事件在所有其他事件之前,且在通過stdoutstderr接收任何資料之前。

無論在衍生的程序內是否發生錯誤,'spawn'事件都會觸發。 例如,如果bash some-command衍生成功,則'spawn'事件將觸發,儘管bash可能衍生some-command失敗。 當使用{ shell: true }時,此注意事項也適用。