Nodejs spawn 之stdio

spawn,exec,execFile和fork關(guān)系

exec 
  │
execFile         fork
  │               │     
  └─────spawn─────┘          用戶層面
           │
-----------│------------------------
           │
           │                  nodejs內(nèi)部
           │                   
     spawn(位于lib/internal/child_process.js)

從上圖可以看出伊磺,在用戶層面其他的三個(gè)函數(shù)都調(diào)用了child_process.spwan

子進(jìn)程的stdio(標(biāo)準(zhǔn)輸入輸出)

  1. options.stdio的值是字符串時(shí),有以下幾種取值
  • pipe:相當(dāng)于['pipe', 'pipe', 'pipe']屈芜,子進(jìn)程的stdio和父進(jìn)程的stdio通過(guò)管道進(jìn)行連接
  • ignore:相當(dāng)于['ignore','ignore', 'ignore']宙帝,子進(jìn)程的stdio綁定到/dev/null,丟棄數(shù)據(jù)的輸入輸出妇蛀。
  • inherit:繼承父進(jìn)程相關(guān)的stdio,等同于[process.stdin,process.stdout,process.sterr]或者[0,1,2],此時(shí)子進(jìn)程的stdio都是綁定在同一個(gè)地方祥山。
  1. 當(dāng)options.stdio值是數(shù)組的時(shí)候蜕劝,前三個(gè)元素分別代表stdin,stdout,stderr袁梗。如果數(shù)組的元素大于3觉吭,則會(huì)在父子進(jìn)程之間建立額外的通訊通道腾供,他們可能是下面的值.
  • pipe 通過(guò)管道進(jìn)行通訊,管道兩端分別連接父子進(jìn)程鲜滩,父進(jìn)程可以通過(guò)subprocess.stdin,subprocess.stdout,subprocess.stderr來(lái)引用管道的一端伴鳖。子進(jìn)程可以通過(guò)process.stdin, process.stdout, process.stderr來(lái)引用另外一端
  • ipc:額外的通訊通道,通過(guò)ipc channel通訊
  • stream:通過(guò)nodejs 的stream 對(duì)象通訊徙硅,對(duì)象底層文件描述符代表一個(gè)文件榜聂。如:socket,tty,本地文件
  • null, undefined,對(duì)于前三個(gè)元素嗓蘑,他們會(huì)設(shè)置為pipe,剩下的元素會(huì)設(shè)置為ignore

例子

  1. pipe
    綁定到父進(jìn)程的process.stdio中
const child_process = require("child_process");
const script = (function(data) {
  console.log(data);
}).toString();
const node = child_process.spawn("node", ["-e", `( ${script}("pipe须肆,只能通過(guò)父進(jìn)程將它輸出") )`], {
  stdio: 'pipe'
});
node.stdout.on('data', data => {
  console.log(data.toString())
})
  1. inherit
const child_process = require("child_process");
const script = (function(data) {
  console.log(data);
}).toString();
child_process.spawn("node", ["-e", `( ${script}("inherit,這一般個(gè)會(huì)寫(xiě)到控制臺(tái)") )`], {
  stdio: [process.stdin, process.stdout, process.stderr]
  // 和 stdio: 'inherit'相似
});
  1. 綁定文件描述符(fd)
const child_process = require("child_process");
const fd = require("fs").openSync("./node.log", "w+");
const script = (function(data) {
  console.log(data);
}).toString();

const node = child_process.spawn("node", ["-e", `( ${script}("整數(shù)fd桩皿,這一般個(gè)會(huì)寫(xiě)到某個(gè)文件") )`], {
  //stdio綁定到文件描述符fd豌汇,它代表文件node.log,因此會(huì)輸出到該文件
  stdio: [process.stdin, fd, fd]
});
  1. 綁定stream
const child_process = require("child_process");
const fd = require("fs").openSync("./node.log", "w+");
const script = (function(data) {
  console.log(data);
}).toString();


const writableStream = require("fs").createWriteStream(null, {
  flags: "a",
  fd,
});
child_process.spawn("node", ["-e", `( ${script}("stream业簿,這一般個(gè)會(huì)寫(xiě)到某個(gè)文件") )`], {
  //輸出到流所代表的目的地瘤礁,注意這個(gè)流必須要有文件描述符,否則會(huì)失敗
  //這個(gè)例子中它會(huì)輸出到文件node.log
  stdio: [process.stdin, writableStream, fd]
});
  1. ipc通道
// parent.js
const child_process = require("child_process");

const node = child_process.spawn("node",['./child.js'], {
  shell:false,
  stdio: ['inherit', 'inherit', 'inherit','ipc']
});

node.send({from: 'parent'});
// child.js
process.on('message', function(m){
  console.log('message from parent: ' + JSON.stringify(m));
});
process.send({from: 'child'});

detached 和守護(hù)進(jìn)程

生成子進(jìn)程的時(shí)候如果傳遞了detached=true,則使得子進(jìn)程成為新的sessiongroup的leader

const child_process = require("child_process");
const ping = child_process.spawn("ping", ["localhost"], {
    detached:true,
    stdio: 'ignore'
});
ping.unref();

需要成為守護(hù)進(jìn)程梅尤,必須要做到以下幾點(diǎn)

  • 子進(jìn)程必須和父進(jìn)程分離柜思,即detached=true
  • 默認(rèn)情況下父進(jìn)程會(huì)等待已分離的子進(jìn)程岩调,調(diào)用subprocess.unref()來(lái)取消等待
  • 子進(jìn)程的IO和父進(jìn)程不能聯(lián)系。使用stdio: 'ignore'

refer

https://cnodejs.org/topic/5aa0e25a19b2e3db18959bee

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末赡盘,一起剝皮案震驚了整個(gè)濱河市号枕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌陨享,老刑警劉巖葱淳,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異抛姑,居然都是意外死亡赞厕,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)定硝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)皿桑,“玉大人,你說(shuō)我怎么就攤上這事蔬啡』逦辏” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵箱蟆,是天一觀的道長(zhǎng)沟绪。 經(jīng)常有香客問(wèn)我,道長(zhǎng)空猜,這世上最難降的妖魔是什么绽慈? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮抄肖,結(jié)果婚禮上久信,老公的妹妹穿的比我還像新娘。我一直安慰自己漓摩,他們只是感情好裙士,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著管毙,像睡著了一般腿椎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上夭咬,一...
    開(kāi)封第一講書(shū)人閱讀 51,182評(píng)論 1 299
  • 那天啃炸,我揣著相機(jī)與錄音,去河邊找鬼卓舵。 笑死南用,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播裹虫,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼肿嘲,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了筑公?” 一聲冷哼從身側(cè)響起雳窟,我...
    開(kāi)封第一講書(shū)人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎匣屡,沒(méi)想到半個(gè)月后封救,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡捣作,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年誉结,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片券躁。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡搓彻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嘱朽,到底是詐尸還是另有隱情,我是刑警寧澤怔接,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布搪泳,位于F島的核電站,受9級(jí)特大地震影響扼脐,放射性物質(zhì)發(fā)生泄漏岸军。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一瓦侮、第九天 我趴在偏房一處隱蔽的房頂上張望艰赞。 院中可真熱鬧,春花似錦肚吏、人聲如沸方妖。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)党觅。三九已至,卻和暖如春斋泄,著一層夾襖步出監(jiān)牢的瞬間杯瞻,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工炫掐, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留魁莉,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像旗唁,于是被迫代替她去往敵國(guó)和親畦浓。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353