nodejs-Child Process模塊

Child Process模塊

來自《JavaScript 標準參考教程(alpha)》,by 阮一峯javascript

目錄

child_process模塊用於新建子進程。子進程的運行結果儲存在系統緩存之中(最大200KB),等到子進程運行結束之後,主進程再用回調函數讀取子進程的運行結果。html

exec()

exec方法用於執行bash命令,它的參數是一個命令字符串。java

var exec = require('child_process').exec; var ls = exec('ls -l', function (error, stdout, stderr) { if (error) { console.log(error.stack); console.log('Error code: ' + error.code); } console.log('Child Process STDOUT: ' + stdout); }); 

上面代碼的exec方法用於新建一個子進程,而後緩存它的運行結果,運行結束後調用回調函數。node

exec方法最多能夠接受兩個參數,第一個參數是所要執行的shell命令,第二個參數是回調函數,該函數接受三個參數,分別是發生的錯誤、標準輸出的顯示結果、標準錯誤的顯示結果。git

因爲標準輸出和標準錯誤都是流對象(stream),能夠監聽data事件,所以上面的代碼也能夠寫成下面這樣。github

var exec = require('child_process').exec; var child = exec('ls -l'); child.stdout.on('data', function(data) { console.log('stdout: ' + data); }); child.stderr.on('data', function(data) { console.log('stdout: ' + data); }); child.on('close', function(code) { console.log('closing code: ' + code); }); 

上面的代碼還代表,子進程自己有close事件,能夠設置回調函數。shell

上面的代碼還有一個好處。監聽data事件之後,能夠實時輸出結果,不然只有等到子進程結束,纔會輸出結果。因此,若是子進程運行時間較長,或者是持續運行,第二種寫法更好。數組

下面是另外一個例子,假定有一個child.js文件。緩存

// child.js var exec = require('child_process').exec; exec('node -v', function(error, stdout, stderr) { console.log('stdout: ' + stdout); console.log('stderr: ' + stderr); if (error !== null) { console.log('exec error: ' + error); } }); 

運行後,該文件的輸出結果以下。安全

$ node child.js stdout: v0.11.14 stderr: 

exec方法會直接調用bash(/bin/sh程序)來解釋命令,因此若是有用戶輸入的參數,exec方法是不安全的。

var path = ";user input"; child_process.exec('ls -l ' + path, function (err, data) { console.log(data); }); 

上面代碼表示,在bash環境下,ls -l; user input會直接運行。若是用戶輸入惡意代碼,將會帶來安全風險。所以,在有用戶輸入的狀況下,最好不使用exec方法,而是使用execFile方法。

execSync()

execSyncexec的同步執行版本。

它能夠接受兩個參數,第一個參數是所要執行的命令,第二個參數用來配置執行環境。

var execSync = require("child_process").execSync; var SEPARATOR = process.platform === 'win32' ? ';' : ':'; var env = Object.assign({}, process.env); env.PATH = path.resolve('./node_modules/.bin') + SEPARATOR + env.PATH; function myExecSync(cmd) { var output = execSync(cmd, { cwd: process.cwd(), env: env }); console.log(output); } myExecSync('eslint .'); 

上面代碼中,execSync方法的第二個參數是一個對象。該對象的cwd屬性指定腳本的當前目錄,env屬性指定環境變量。上面代碼將./node_modules/.bin目錄,存入$PATH變量。這樣就能夠不加路徑,引用項目內部的模塊命令了,好比eslint命令實際執行的是./node_modules/.bin/eslint

execFile()

execFile方法直接執行特定的程序,參數做爲數組傳入,不會被bash解釋,所以具備較高的安全性。

var child_process = require('child_process'); var path = "."; child_process.execFile('/bin/ls', ['-l', path], function (err, result) { console.log(result) }); 

上面代碼中,假定path來自用戶輸入,若是其中包含了分號或反引號,ls程序不理解它們的含義,所以也就得不到運行結果,安全性就獲得了提升。

spawn()

spawn方法建立一個子進程來執行特定命令,用法與execFile方法相似,可是沒有回調函數,只能經過監聽事件,來獲取運行結果。它屬於異步執行,適用於子進程長時間運行的狀況。

var child_process = require('child_process'); var path = '.'; var ls = child_process.spawn('/bin/ls', ['-l', path]); ls.stdout.on('data', function (data) { console.log('stdout: ' + data); }); ls.stderr.on('data', function (data) { console.log('stderr: ' + data); }); ls.on('close', function (code) { console.log('child process exited with code ' + code); }); 

spawn方法接受兩個參數,第一個是可執行文件,第二個是參數數組。

spawn對象返回一個對象,表明子進程。該對象部署了EventEmitter接口,它的data事件能夠監聽,從而獲得子進程的輸出結果。

spawn方法與exec方法很是相似,只是使用格式略有區別。

child_process.exec(command, [options], callback) child_process.spawn(command, [args], [options]) 

fork()

fork方法直接建立一個子進程,執行Node腳本,fork('./child.js') 至關於 spawn('node', ['./child.js']) 。與spawn方法不一樣的是,fork會在父進程與子進程之間,創建一個通訊管道,用於進程之間的通訊。

var n = child_process.fork('./child.js'); n.on('message', function(m) { console.log('PARENT got message:', m); }); n.send({ hello: 'world' }); 

上面代碼中,fork方法返回一個表明進程間通訊管道的對象,對該對象能夠監聽message事件,用來獲取子進程返回的信息,也能夠向子進程發送信息。

child.js腳本的內容以下。

process.on('message', function(m) { console.log('CHILD got message:', m); }); process.send({ foo: 'bar' }); 

上面代碼中,子進程監聽message事件,並向父進程發送信息。

send()

使用 child_process.fork() 生成新進程以後,就能夠用 child.send(message, [sendHandle]) 向新進程發送消息。新進程中經過監聽message事件,來獲取消息。

下面的例子是主進程的代碼。

var cp = require('child_process'); var n = cp.fork(__dirname + '/sub.js'); n.on('message', function(m) { console.log('PARENT got message:', m); }); n.send({ hello: 'world' }); 

下面是子進程sub.js代碼。

process.on('message', function(m) { console.log('CHILD got message:', m); }); process.send({ foo: 'bar' }); 

參考連接

 | last modified on 2014-05-24

相關文章
相關標籤/搜索