Node.js在child_process域和錯(cuò)誤冒泡及捕獲實(shí)踐
child_process
child_進(jìn)程模塊提供派生子進(jìn)程的功能。它與popen(3)相似但不相同。此函數(shù)主要由[child_process.spown()]函數(shù)提供:
const { spawn } = require('child_process'); const ls = spawn('ls', ['-lh', '/usr']); ls.stdout.on('data', (data) => { console.log(`輸出:${data}`); }); ls.stderr.on('data', (data) => { console.log(`錯(cuò)誤:${data}`); }); ls.on('close', (code) => { console.log(`子進(jìn)程退出碼:$[code]`); });
const { exec } = require('child_process'); exec('my.bat', (err, stdout, stderr) => { if (err) { console.error(err); return; } console.log(stdout); }); // 文件名帶有空格的腳本: const bat = spawn('"my script.cmd"', ['a', 'b'], { shell: true }); // 或: exec('"my script.cmd" a b', (err, stdout, stderr) => { // ... });
child_進(jìn)程模塊還提供一些其他同步和異步可選功能。每個(gè)函數(shù)都是基于[child_process.spawn()]或[child_process.spawnSync()]實(shí)現(xiàn)的。
[child_process.exec()]:派生一個(gè)shell并在該shell上運(yùn)行命令。完成后,stdout和stderr將傳遞給回調(diào)函數(shù)。
const { spawn } = require('child_process'); const grep = spawn('grep', ['ssh']); grep.on('close', (code, signal) => { console.log(`子進(jìn)程收到信號(hào) ${signal} 而終止`); }); // 發(fā)送 SIGHUP 到進(jìn)程 grep.kill('SIGHUP');
[child_process.execFile()]:類似于[child_procedure.exec()],但命令是直接派生的,而不首先派生shell。
[child_process.f分叉()]:派生一個(gè)新的NodeJs進(jìn)程,并通過(guò)建立IPC通信通道調(diào)用指定的模塊,這允許父進(jìn)程和子進(jìn)程相互發(fā)送信息。
[child_process.execSync()]:[child_procedure.exec()]的同步函數(shù)阻止節(jié)點(diǎn)J的事件循環(huán)。
[child_process.execFileSync()]:[child_cess.execFile()]的同步函數(shù)阻止節(jié)點(diǎn)J的事件循環(huán)。
options.detached
在Windows上,設(shè)置選項(xiàng)如果分離為true,則子進(jìn)程可以在父進(jìn)程退出后繼續(xù)運(yùn)行。子進(jìn)程有自己的控制臺(tái)窗口。一旦啟用了子進(jìn)程,就不能禁用它。
在非Windows平臺(tái)上,如果選項(xiàng)if detached設(shè)置為true,則子進(jìn)程將成為新進(jìn)程組和會(huì)話的領(lǐng)導(dǎo)者。請(qǐng)注意,子進(jìn)程可以在父進(jìn)程退出后繼續(xù)運(yùn)行,無(wú)論它們是否分離。
詳見setsid(2)。
const fs = require('fs'); const { spawn } = require('child_process'); const out = fs.openSync('./out.log', 'a'); const err = fs.openSync('./out.log', 'a'); const subprocess = spawn('prg', [], { detached: true, stdio: [ 'ignore', out, err ] }); subprocess.unref();
默認(rèn)情況下,父進(jìn)程將等待分離的子進(jìn)程退出。為了防止父進(jìn)程等待給定的子進(jìn)程,可以使用子進(jìn)程Unref()方法。這將導(dǎo)致父進(jìn)程的事件循環(huán)排除子進(jìn)程的引用計(jì)數(shù),使父進(jìn)程獨(dú)立于子進(jìn)程退出,除非在子進(jìn)程和父進(jìn)程之間建立了IPC通道。
使用分離選項(xiàng)啟動(dòng)長(zhǎng)時(shí)間運(yùn)行的進(jìn)程時(shí),除非提供了未連接到父進(jìn)程的stdio配置,否則父進(jìn)程退出后,該進(jìn)程將不會(huì)在后臺(tái)繼續(xù)運(yùn)行。如果繼承了父進(jìn)程的stdio,則子進(jìn)程將保持與控制終端的連接。
例如,對(duì)于長(zhǎng)時(shí)間運(yùn)行的進(jìn)程,為了忽略父進(jìn)程的終止,父進(jìn)程的stdio文件描述符被分離并忽略:
const { spawn } = require('child_process'); const subprocess = spawn(process.argv[0], ['child_program.js'], { detached: true, stdio: 'ignore' }); subprocess.unref();
如果未傳遞信號(hào),[ChildProcess]對(duì)象可能會(huì)觸發(fā)['error']事件。向已退出的子進(jìn)程發(fā)送信號(hào)不是錯(cuò)誤,但可能會(huì)產(chǎn)生不可預(yù)測(cè)的后果。
特別是,如果一個(gè)進(jìn)程的PID被重新分配給另一個(gè)進(jìn)程,則該信號(hào)將被發(fā)送給該進(jìn)程,這可能會(huì)導(dǎo)致意外的結(jié)果。
注意,當(dāng)函數(shù)被稱為kill時(shí),發(fā)送給子進(jìn)程的信號(hào)實(shí)際上可能不會(huì)終止該進(jìn)程。
'use strict'; const { spawn } = require('child_process'); const subprocess = spawn( 'sh', [ '-c', `node -e "setInterval(() => { console.log(process.pid, 'is alive') }, 500);"` ], { stdio: ['inherit', 'inherit', 'inherit'] } ); setTimeout(() => { subprocess.kill(); // 不會(huì)終止 shell 中的 node 進(jìn)程 }, 2000);
一旦套接字被傳遞給子進(jìn)程,父進(jìn)程就無(wú)法再跟蹤套接字何時(shí)被銷毀。若要顯示此屬性,連接屬性將變?yōu)榭?。發(fā)生這種情況時(shí),不建議使用。
最大連接數(shù)。 建議子進(jìn)程中的任何消息處理程序都應(yīng)驗(yàn)證套接字是否存在,因?yàn)檫B接在發(fā)送到子進(jìn)程期間可能會(huì)關(guān)閉。
cipher.update
用數(shù)據(jù)更新密碼。如果給定inputEncoding參數(shù),其值必須為“utf8”、“ascii”或“latin1”,并且數(shù)據(jù)參數(shù)是使用指定編碼的字符串。如果未給定inputEncoding參數(shù),則數(shù)據(jù)必須為Buffer、TypedArray或DataView。如果數(shù)據(jù)是Buffer、TypedArray或DataView,則忽略inputEncoding。
OutputEncoding指定加密數(shù)據(jù)的輸出格式,可以是“latin1”、“base64”或“hex”。如果指定了outputEncoding,則返回具有指定編碼的字符串。如果未提供outputEncoding,將返回Buffer。 密碼。
update()方法可以用新數(shù)據(jù)多次調(diào)用,直到調(diào)用密碼Final()。
['cipher.final()'][]調(diào)用密碼。update()。
final()將拋出錯(cuò)誤。
const crypto = require('crypto'); const decipher = crypto.createDecipher('aes192', 'a password'); let decrypted = ''; decipher.on('readable', () => { const data = decipher.read(); if (data) decrypted += data.toString('utf8'); }); decipher.on('end', () => { console.log(decrypted); // Prints: some clear text data }); const encrypted = 'ca981be48e90867604588e75d04feabb63cc007a8f8ad89b10616ed84d815504'; decipher.write(encrypted, 'hex'); decipher.end();
const crypto = require('crypto'); const fs = require('fs'); const decipher = crypto.createDecipher('aes192', 'a password'); const input = fs.createReadStream('test.enc'); const output = fs.createWriteStream('test.js'); input.pipe(decipher).pipe(output);
返回所有剩余的解密內(nèi)容。如果outputEncoding參數(shù)是“latin1”、“ascii”或“utf8”之一,則返回字符串。如果未提供輸出編碼,則返回Buffer。
一旦解密了final()方法,decipher對(duì)象就不能再用于解密數(shù)據(jù)。正在嘗試調(diào)用解密。final()多次導(dǎo)致拋出錯(cuò)誤。
const crypto = require('crypto'); const assert = require('assert'); // Generate Alice's keys... const alice = crypto.createDiffieHellman(2048); const aliceKey = alice.generateKeys(); // Generate Bob's keys... const bob = crypto.createDiffieHellman(alice.getPrime(), alice.getGenerator()); const bobKey = bob.generateKeys(); // Exchange and generate the secret... const aliceSecret = alice.computeSecret(bobKey); const bobSecret = bob.computeSecret(aliceKey); // OK assert.strictEqual(aliceSecret.toString('hex'), bobSecret.toString('hex'));
錯(cuò)誤的冒泡和捕獲
節(jié)點(diǎn)。Js支持幾種機(jī)制來(lái)冒泡和處理應(yīng)用程序運(yùn)行時(shí)發(fā)生的錯(cuò)誤。如何報(bào)告和處理這些錯(cuò)誤完全取決于錯(cuò)誤的類型和調(diào)用的API的樣式。 所有JavaScript錯(cuò)誤都將被視為異常。將立即生成異常,并使用標(biāo)準(zhǔn)JavaScript拋出機(jī)制拋出錯(cuò)誤。這些都是使用JavaScript語(yǔ)言提供的try/catch語(yǔ)句處理的。
try { const m = 1; const n = m + z; } catch (err) { // 在這里處理錯(cuò)誤。 }
任何使用JavaScript的拋出機(jī)制都會(huì)導(dǎo)致異常。異常必須用try/catch處理,否則Node.js進(jìn)程將立即退出。 除了少數(shù)例外,同步API(任何不接受回調(diào)函數(shù)的阻塞方法,如[fs.readFileSync])將使用throw來(lái)報(bào)告錯(cuò)誤。 異步API中的錯(cuò)誤可以通過(guò)幾種方式報(bào)告: 大多數(shù)異步方法都接受回調(diào)函數(shù),該函數(shù)接受Error對(duì)象作為第一個(gè)參數(shù)。如果第一個(gè)參數(shù)不是null,而是一個(gè)Error實(shí)例,則表示發(fā)生了錯(cuò)誤,應(yīng)進(jìn)行處理。
以上就是Node.js在child_process域和錯(cuò)誤冒泡及捕獲實(shí)踐的詳細(xì)內(nèi)容,更多關(guān)于Node.js child_process錯(cuò)誤捕獲的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
手寫Node靜態(tài)資源服務(wù)器的實(shí)現(xiàn)方法
這篇文章主要介紹了手寫Node靜態(tài)資源服務(wù)器的實(shí)現(xiàn)方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03Node.js npm命令運(yùn)行node.js腳本的方法
今天小編就為大家分享一篇Node.js npm命令運(yùn)行node.js腳本的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-10-10node.js中使用q.js實(shí)現(xiàn)api的promise化
這篇文章主要介紹了node.js中使用q.js實(shí)現(xiàn)api的promise化,promise一個(gè)標(biāo)準(zhǔn),它描述了異步調(diào)用的返回結(jié)果,包括正確返回結(jié)果和錯(cuò)誤處理,需要的朋友可以參考下2014-09-09詳解如何實(shí)現(xiàn)一個(gè)簡(jiǎn)單的Node.js腳手架
本篇文章主要介紹了如何實(shí)現(xiàn)一個(gè)簡(jiǎn)單的Node.js腳手架,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-12-12Nodejs+express+ejs簡(jiǎn)單使用實(shí)例代碼
本篇文章主要介紹了Nodejs+express+ejs簡(jiǎn)單使用實(shí)例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09