exec 和 spawn 的區別


參考資料:

最近在用nodejs 的child_process 模塊調用系統的shell腳本,但是發現遇到一些問題

  1. child_process.exec 方法調用shell腳本發現內容過長會拋錯 Error: maxBuffer exceeded(和options.maxBuffer有關)
  2. child_process.spawn 方法調用shell腳本發現控制台無法監聽用戶的輸入(和options. stdio 設置有關)
  3. nodejs 調用 shell 后,shell里面的命令找不到(和options.env有關)
  4. nodejs 如何傳入 env 到shell里(和options.env有關)

spawn 和 exec 的區別

總體來說 spawn 返回一個stream,exec返回一個buffer

child_process.spawn 返回一個有輸出流和錯誤的流的對象,你可以監聽它們從而獲取數據,輸出流有數據和結束事件,child_process.spawn 適合用在處理大量數據返回的場景中,圖片處理,讀二進制數據等等。

child_process.spawn是一個異步的異步函數,怎么解釋呢?child_process.spawn 在執行時就會返回數據,而不是等到數據都處理好了再一次返回。

child_process.exec 一次性返回輸出執行結果內容,默認的buffer大小為200kb,如果exec返回的內容超過 200kb則會返回一個錯誤:Error maxBuffer execeded,你可以通過設置options buffer的size來擴大 buffer 的大小。

child_process.exec 是一個同步的異步方法,這個意思是,雖然方法體本身是異步的,但是它要等 child process 執行完成后,再把返回數據一口氣返回給回調方法。如果返回內容超過了設置的buffer size,則會返回一個maxBuffer exceeded 錯誤。

options.stdio

options.stdio 選項用於配置子進程與父進程之間建立的管道。 默認情況下,子進程的 stdin、 stdout 和 stderr 會重定向到 ChildProcess 對象上相應的 child.stdinchild.stdoutchild.stderr 流。 這等同於將 options.stdio 設為 ['pipe', 'pipe', 'pipe']。

這個配置不一定是數組,也可以是字符串,

  • pipe == [‘pipe', 'pipe', 'pipe']
  • ignore == ['ignore', 'ignore', 'ignore']
  • inherit == [process.stdin, process.stdout, process.stderr] 流會定向到你系統的bash 環境中,nodejs不再接管錯誤、數據的處理
let ls = spawn('ls', ['-al'], {
  stdio: ['pipe', 'pipe', 'pipe']
});

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

這種情況下,子進程的數據會返回給父進程,也就是nodejs,然后你可以監聽流的輸出。

設置 stdio 為 ‘inherit’

let ls = spawn('ls', ['-al'], {
  stdio: ['inherit', 'inherit', 'inherit']
});

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

會拋出錯誤,

ls.stdout.on('data', (data) => {
			^
TypeError: Cannot read property 'on' of null

但是你在控制台應該可以看到數據,這個數據是bash執行的結果

傳入shell的環境變量

使用 options.env 可以傳入變量,在 shell中可以直接使用。

test_shell.js

#! /bin/bash

echo $NAME

test_child_process.js

let spawn = require("child_process").spawn;

let options = {
  stdio: 'inherit',
  env: Object.assign({NAME: "cowboy"}, process.env)
}

spawn('sh', ['./test_shell.sh'], options);

輸出

cowboy


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM