Node.js在child_process域和錯誤冒泡及捕獲實踐
child_process
child_進程模塊提供派生子進程的功能。它與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(`錯誤:${data}`); }); ls.on('close', (code) => { console.log(`子進程退出碼:$[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_進程模塊還提供一些其他同步和異步可選功能。每個函數(shù)都是基于[child_process.spawn()]或[child_process.spawnSync()]實現(xiàn)的。
[child_process.exec()]:派生一個shell并在該shell上運行命令。完成后,stdout和stderr將傳遞給回調函數(shù)。
const { spawn } = require('child_process'); const grep = spawn('grep', ['ssh']); grep.on('close', (code, signal) => { console.log(`子進程收到信號 ${signal} 而終止`); }); // 發(fā)送 SIGHUP 到進程 grep.kill('SIGHUP');
[child_process.execFile()]:類似于[child_procedure.exec()],但命令是直接派生的,而不首先派生shell。
[child_process.f分叉()]:派生一個新的NodeJs進程,并通過建立IPC通信通道調用指定的模塊,這允許父進程和子進程相互發(fā)送信息。
[child_process.execSync()]:[child_procedure.exec()]的同步函數(shù)阻止節(jié)點J的事件循環(huán)。
[child_process.execFileSync()]:[child_cess.execFile()]的同步函數(shù)阻止節(jié)點J的事件循環(huán)。
options.detached
在Windows上,設置選項如果分離為true,則子進程可以在父進程退出后繼續(xù)運行。子進程有自己的控制臺窗口。一旦啟用了子進程,就不能禁用它。
在非Windows平臺上,如果選項if detached設置為true,則子進程將成為新進程組和會話的領導者。請注意,子進程可以在父進程退出后繼續(xù)運行,無論它們是否分離。
詳見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();
默認情況下,父進程將等待分離的子進程退出。為了防止父進程等待給定的子進程,可以使用子進程Unref()方法。這將導致父進程的事件循環(huán)排除子進程的引用計數(shù),使父進程獨立于子進程退出,除非在子進程和父進程之間建立了IPC通道。
使用分離選項啟動長時間運行的進程時,除非提供了未連接到父進程的stdio配置,否則父進程退出后,該進程將不會在后臺繼續(xù)運行。如果繼承了父進程的stdio,則子進程將保持與控制終端的連接。
例如,對于長時間運行的進程,為了忽略父進程的終止,父進程的stdio文件描述符被分離并忽略:
const { spawn } = require('child_process'); const subprocess = spawn(process.argv[0], ['child_program.js'], { detached: true, stdio: 'ignore' }); subprocess.unref();
如果未傳遞信號,[ChildProcess]對象可能會觸發(fā)['error']事件。向已退出的子進程發(fā)送信號不是錯誤,但可能會產(chǎn)生不可預測的后果。
特別是,如果一個進程的PID被重新分配給另一個進程,則該信號將被發(fā)送給該進程,這可能會導致意外的結果。
注意,當函數(shù)被稱為kill時,發(fā)送給子進程的信號實際上可能不會終止該進程。
'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(); // 不會終止 shell 中的 node 進程 }, 2000);
一旦套接字被傳遞給子進程,父進程就無法再跟蹤套接字何時被銷毀。若要顯示此屬性,連接屬性將變?yōu)榭铡0l(fā)生這種情況時,不建議使用。
最大連接數(shù)。 建議子進程中的任何消息處理程序都應驗證套接字是否存在,因為連接在發(fā)送到子進程期間可能會關閉。
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ù)多次調用,直到調用密碼Final()。
['cipher.final()'][]調用密碼。update()。
final()將拋出錯誤。
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);
返回所有剩余的解密內容。如果outputEncoding參數(shù)是“latin1”、“ascii”或“utf8”之一,則返回字符串。如果未提供輸出編碼,則返回Buffer。
一旦解密了final()方法,decipher對象就不能再用于解密數(shù)據(jù)。正在嘗試調用解密。final()多次導致拋出錯誤。
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'));
錯誤的冒泡和捕獲
節(jié)點。Js支持幾種機制來冒泡和處理應用程序運行時發(fā)生的錯誤。如何報告和處理這些錯誤完全取決于錯誤的類型和調用的API的樣式。 所有JavaScript錯誤都將被視為異常。將立即生成異常,并使用標準JavaScript拋出機制拋出錯誤。這些都是使用JavaScript語言提供的try/catch語句處理的。
try { const m = 1; const n = m + z; } catch (err) { // 在這里處理錯誤。 }
任何使用JavaScript的拋出機制都會導致異常。異常必須用try/catch處理,否則Node.js進程將立即退出。 除了少數(shù)例外,同步API(任何不接受回調函數(shù)的阻塞方法,如[fs.readFileSync])將使用throw來報告錯誤。 異步API中的錯誤可以通過幾種方式報告: 大多數(shù)異步方法都接受回調函數(shù),該函數(shù)接受Error對象作為第一個參數(shù)。如果第一個參數(shù)不是null,而是一個Error實例,則表示發(fā)生了錯誤,應進行處理。
以上就是Node.js在child_process域和錯誤冒泡及捕獲實踐的詳細內容,更多關于Node.js child_process錯誤捕獲的資料請關注腳本之家其它相關文章!
相關文章
node.js中使用q.js實現(xiàn)api的promise化
這篇文章主要介紹了node.js中使用q.js實現(xiàn)api的promise化,promise一個標準,它描述了異步調用的返回結果,包括正確返回結果和錯誤處理,需要的朋友可以參考下2014-09-09