在瞭解child_processz以前,咱們先來了解幾個計算機操做系統中的基本概念,以及他們之間存在的關係。html
cup: 計算機包含五大基本硬件運算器、控制器、存儲器、輸入,輸出設備。運算器和控制器集成爲中央處理單元即CPU(Central Processing Unit),其主要做用是執行一系列指令運算而後將結果寫回。node
進程: 進程是系統進行資源分配和調度的基本單位,同一時間在單個CUP上只能有一個進程運行,它會佔用獨立的內存。可是咱們可能會想到,計算機運行的時候確定不僅是隻有一個進程在運行。在現代操做系統中,全部進程會輪流使用cpu,可是因爲cpu的運行效率極高,能夠在多個任務間快速切換,給咱們的感受就好像多個任務在併發執行。shell
線程: 線程是進程中的實體,一個進程能夠擁有多個線程,一個線程必須有一個父進程。線程不擁有系統資源,線程共享該進程所擁有的所有資源,可是當有其中一個線程使用某一塊共享內存的時候,其餘線程必須等待它結束後,才能使用這一塊內存。api
咱們知道node是單線程運行的,當咱們用node app.js啓動node服務的時候會在服務器上運行一個node的進程,咱們的js代碼只會在其中的一個線程運行。在node的設計中就是將耗時長的操做代理給操做系統或者其餘線程,這部分操做就是磁盤I/O和網絡I/O等常見的異步操做,而且將這些耗時的操做從主線程上脫離。雖然node從語言層面不支持建立線程,可是咱們能夠經過child_process模塊建立一個新的進程完成耗時耗費資源的操做,好比說要執行一段上傳或下載大文件的shell腳本,而後將執行結果回傳給主線程。服務器
使用child_process建立子進程的方式主要有如下四種:
exec、execFile、spawn、fork、
關於其各自的用法請自行查閱文檔
process_child文檔網絡
這裏咱們只對一些重要的須要注意的點,以及他們各自的使用場景作一個總結併發
child_process.exec(command, {...config}, (err, stdout, stderr) => {})
在exec方法的第二個參數中有這麼一項配置即{maxBuffer: 200 * 1024}。它表示stdout、stderr 容許的最大輸出大小(以 byte 爲單位),若是超過了,子進程將被 kill 掉(發送 killSignal 值),它的默認值是200kb,這也就很大程度上決定了它的實用場景,即在子進程長時間運行或者大量的日誌輸出時,須要謹慎設置maxBuffer的值。這種狀況下使用spawn方法更爲合適。app
spawn(command, args, config)
spawn方式適合用在進程的輸入、輸出數據量比較大的狀況能夠用於任何命令。可是它與exec方法比較起來就是在執行多條命令的時候使用起來可能不太方便。若是咱們要執行多條命令,能夠經過新建shell腳本的方式來實現。ssh
import { spawn } from 'child_process' const child = spawn('sh', [path.join(__dirname, './test.sh'), '192.100.100.100'])
而後在shell腳本里面執行下面的命令異步
ssh suoper@$1 << eeooff cd ${apiConfig.apkUpload.path} exit eeooff
fork(filePath, args, options)
fork命令只能執行用來執行node腳本,同事會建立一個新的V8實例。
execFile(file, args, options, callback)
須要注意的是,exec 會首先建立一個新的 shell 進程出來,而後執行 command。execFile 則是直接將可執行的 file 建立爲新進程執行。因此,execfile 會比 exec 高效一些。exec 比較適合用來執行 shell 命令,而後獲取輸出(好比:exec('ps aux | grep "node"')),可是 execFile 卻沒辦法這麼用,由於它實際上只接受一個可執行的命令,而後執行(無法使用 shell 裏面的管道之類的東西)。