child_process使用記錄

建立子進程的幾種方式

一、child_process.exec(command[, options][, callback])
二、child_process.execFile(file[, args][, options][, callback])
三、child_process.fork(modulePath[, args][, options])
四、child_process.spawn(command[, args][, options])
其中exec,execFile,fork均是從spawn衍生出來。javascript

通道的創建和原理

stdout,stdin,stderr是共享了父進程的文件操做符,因此咱們能夠經過建立文件操做符來進行進程間共享,建立方法是fs.open或者fs.openSyncjava

這四種的區別(只關注重點區別)

一、child_process.exec(command[, options][, callback])

特色:
(1)衍生一個shell,而後在shell執行命令。至關於把command直接發送給shell執行。
(2)具備回調函數子進程結束或者意外退出會調用回調方法
(3)具備maxbuffer,stdout 或 stderr 上容許的最大字節數。若是超過限制,則子進程將終止。默認值: 200 * 1024。也由於如此,因此exec啓用的子進程不適合與父進程發送大量數據。
(4)timeout,設置子進程的運行時間,若是大於0,子進程會在設定的時間事後接收到父進程發送的帶 killSignal 屬性(默認爲 'SIGTERM')的信號。node

二、child_process.execFile(file[, args][, options][, callback])

特色:
(1)用於執行可執行文件
(2)不衍生shell,使用可執行 file 直接做爲新進程衍生,使其比 child_process.exec() 稍微更高效。
(3)具備maxbuffer,stdout 或 stderr 上容許的最大字節數。若是超過限制,則子進程將終止。默認值: 200 * 1024。也由於如此,因此exec啓用的子進程不適合與父進程發送大量數據。
(4)timeout,設置子進程的運行時間,若是大於0,子進程會在設定的時間事後接收到父進程發送的帶 killSignal 屬性(默認爲 'SIGTERM')的信號。
(5)因爲沒有生成 shell,所以不支持 I/O 重定向和文件通配等行爲。shell

三、child_process.fork(modulePath[, args][, options])

特色:
(1)是 child_process.spawn() 的一個特例,專門用於衍生新的 Node.js 進程。
(2)與 child_process.spawn() 同樣返回 ChildProcess 對象。 返回的 ChildProcess 會內置一個額外的通訊通道,容許消息在父進程和子進程之間來回傳遞。
(3)shell 選項在 child_process.fork() 中不支持,若是設置則會被忽略。
(4)能夠設置stdio,可是必須包含一個額外的ipc通道
(5)能夠在配置中指定execPath,這樣即可以使用不一樣的node版本啓動進程了函數

四、child_process.spawn(command[, args][, options])

特色:
(1)以上三個方法有的功能均能經過這個方法實現
ui

實現功能

一、child_process.spawn(command[, args][, options])

這個方法能實現的功能比較多。
一、實現子進程經過stdio配置往一個文件中寫內容編碼

//主進程
const {spawn}=require('child_process');
const fs=require('fs');

//獲取文件描述符
let fd=fs.openSync('./a.temp','r+');

let child1=spawn('node',['./child1.js'],{
    stdio:['pipe',fd,'pipe']
});
複製代碼
//子進程

process.stdin.on('data',(data)=>{
    console.log(data)
})
setInterval(()=>{
    process.stdout.write('哈哈哈','utf-8')
},20)

複製代碼

二、指定環境變量
spa

//主進程
const {exec}=require('child_process');

let child=exec('node ./child.js',{
    env:{
        mode:'dev'
    }
},(err,stdout,stderr)=>{
    console.log(stdout)
})
//child
process.stdout.write(process.env.mode)
//輸出dev
複製代碼

三、父子進程解除引用
解除引用大的前提有如下幾點:
(1)、父子進程之間不能共享stdio,ipc。
(2)、detached:true,須要配置此項。
code

//讓父進程脫離子進程配置
let child= spawn('node',['./child.js'],{detached:true,stdio:"ignore"})
複製代碼

四、設置編碼
如下演示設置編碼的兩種方式。
對象

const {spawn,exec}=require('child_process');

//使用spawn的編碼方式
let childSpawn=spawn('node',['-v']);
childSpawn.stdout.setEncoding('utf8');

childSpawn.stdout.on('data',(data)=>{
    console.log(data)
})

//這種方式顯而更簡單
let childExec=exec('node -v',{encoding:'utf8'},(err,stdout,stdin)=>{

})

childExec.stdout.on('data',(data)=>{
    console.log(data)
})

複製代碼

五、設置maxBuffer
maxBuffer的含義是接受到的字節總數,這個的做用是能夠防止父進程不處理數據子進程一直寫入致使內存爆掉。

//主進程
const {spawn,exec}=require('child_process');

let  maxBufferLength=1024*1200;
let childSpawn=spawn('node',['./child.js']);
let  sum=0;
childSpawn.stdout.on('data',(data)=>{
    sum=sum+Buffer.byteLength(data);
    if(sum>=maxBufferLength){
        childSpawn.kill('SIGTERM')
    }
})
childSpawn.on('exit',(code,sig)=>{
    console.log(sig)
})

//使用exec限流

let  childExec=exec('node ./child.js',{maxBuffer:maxBufferLength},(err,stdout,stderr)=>{
    console.log(err)
})

childExec.on('exit',(code,sig)=>{
    console.log(sig)
})
//child.js
setInterval(()=>{
    process.stdout.write(Buffer.alloc(1024*400,"hha"))
},1000)
複製代碼

六、設置timeOut
設置timeOut

const {spawn,exec}=require('child_process');

let  timeOut=3000;
let childSpawn=spawn('node',['./child.js']);
childSpawn.stdout.on('data',(data)=>{
   
})
setTimeout(()=>{
    childSpawn.kill('SIGTERM')
},timeOut);

childSpawn.on('exit',(code,sig)=>[
    console.log(sig)
])

//使用exec設置超時
let  childExec=exec('node ./child.js',{timeout:timeOut},(err,stdout,stderr)=>{
    console.log(err)
})

childExec.on('exit',(code,sig)=>[
    console.log(sig)
])
//child.js
setInterval(()=>{
    process.stdout.write(Buffer.alloc(1024*400,"hha"))
},1000)
複製代碼
相關文章
相關標籤/搜索