2013-01-15 248 views
45

我有一個腳本,輸出'嗨',睡一秒,輸出'嗨',睡1秒,等等等等。現在我想我可以用這個模型解決這個問題。Node.js產生子進程並獲得終端輸出生活

var spawn = require('child_process').spawn, 
temp = spawn('PATH TO SCRIPT WITH THE ABOVE BEHAVIOUR'); 

temp.stdout.pipe(process.stdout); 

現在問題是需要完成任務才能顯示輸出。正如我所理解的,這是由於新產生的進程需要執行控制。顯然node.js不支持線程,所以任何解決方案?我的想法是可能運行兩個實例,第一個實例用於創建任務的具體目的,並將其輸出到第二個實例的進程中,考慮到這可以實現。

回答

52

我還在用Node.js弄溼我的腳,但我有一些想法。首先,我相信你需要使用execFile而不是spawn; execFile適用於具有指向腳本的路徑,而spawn用於執行Node.js可以根據系統路徑解析的衆所周知的命令。

1. Provide a callback處理緩衝輸出:

var child = require('child_process').execFile('path/to/script', [ 
    'arg1', 'arg2', 'arg3', 
], function(err, stdout, stderr) { 
    // Node.js will invoke this callback when the 
    console.log(stdout); 
}); 

2.添加監聽器子進程的標準輸出stream9thport.net

var child = require('child_process').execFile('path/to/script', [ 
    'arg1', 'arg2', 'arg3' ]); 
// use event hooks to provide a callback to execute when data are available: 
child.stdout.on('data', function(data) { 
    console.log(data.toString()); 
}); 

此外,似乎有選項,由此您可以從Node的控制終端分離產生的進程,這將允許它異步運行。我沒有測試過這個呢,但也有在API docs能像這樣一些例子:

child = require('child_process').execFile('path/to/script', [ 
    'arg1', 'arg2', 'arg3', 
], { 
    // detachment and ignored stdin are the key here: 
    detached: true, 
    stdio: [ 'ignore', 1, 2 ] 
}); 
// and unref() somehow disentangles the child's event loop from the parent's: 
child.unref(); 
child.stdout.on('data', function(data) { 
    console.log(data.toString()); 
}); 
+5

獎勵積分,你可以解釋如何使用EXEC(),因爲我需要執行一個shell CMD做到這一點。 – DynamicDan

+1

你可以使用'child.spawn()''shell'選項設置爲'true'。 https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options – CedX

+1

你也可以通過'child.stdout.pipe(process.stdout);' – darkadept

1

孩子:

setInterval(function() { 
    process.stdout.write("hi"); 
}, 1000); // or however else you want to run a timer 

父:

require('child_process').fork('./childfile.js'); 
// fork'd children use the parent's stdio 
60

現在容易得多(2年後)!

Spawn返回一個childObject,然後您可以使用監聽事件。這些事件是:

  • 類:子進程
    • 事件: '錯誤'
    • 事件: '退出'
    • 事件: '關閉'
    • 事件: '斷開'
    • 事件:'message'

也有一堆從childObject對象,它們分別是:

  • 類:子進程
    • child.stdin
    • child.stdout
    • child.stderr
    • 孩子.stdio
    • child.pid
    • child.connected
    • child.kill([信號])
    • child.send(消息[,sendHandle] [,回調])
    • child.disconnect()

見更多信息,這裏大約childObject:https://nodejs.org/api/child_process.html

因此,結合這一切,你會得到:

var spawn = require('child_process').spawn; 
var child = spawn('node ./commands/server.js'); 
child.stdout.on('data', function(data) { 
    console.log('stdout: ' + data); 
    //Here is where the output goes 
}); 
child.stderr.on('data', function(data) { 
    console.log('stderr: ' + data); 
    //Here is where the error output goes 
}); 
child.on('close', function(code) { 
    console.log('closing code: ' + code); 
    //Here you can get the exit code of the script 
}); 

這就是你如何使用Node獲得輸出!

+4

+1將child.stdout直接傳遞給process.stdout,這應該是現在選擇作爲正確答案。請注意,回調中的數據變量以Buffer對象形式出現。你可以使用''''child.stdout.setEncoding('utf8')'''如果你想要utf8字符串進來。 – Ashish

+0

我想運行一個python腳本;它的運行但輸出不會來到這裏。 'var spawn = require('child_process')。spawn; var child = spawn('python',['/my/path/to/python/file/my_python_file.py']); ('data',function(data){ console.log('stdout:'+ data); }); ('data',function(data){ console.log('stderr:'+ data); }); ('close',function(code){ console.log('closing code:'+ code); });'' – ishandutta2007

10

當我在子進程中產生npm時,從「npm install」命令獲取日誌輸出時有點麻煩。父控制檯中不顯示依賴項的實時日誌記錄。

做原來的海報想要什麼,最簡單的方法似乎是這樣的(在Windows上產卵NPM和日誌一切母公司控制檯):

var args = ['install']; 

var options = { 
    stdio: 'inherit' //feed all child process logging into parent process 
}; 

var childProcess = spawn('npm.cmd', args, options); 
childProcess.on('close', function(code) { 
    process.stdout.write('"npm install" finished with code ' + code + '\n'); 
}); 
0

我發現自己需要這個功能往往不夠,我打包它進入名爲std-pour的圖書館。它應該讓你執行一個命令並實時查看輸出。要安裝簡單:

npm install std-pour 

然後它足夠簡單,執行命令,並查看實時輸出:

const { pour } = require('std-pour'); 
pour('ping', ['8.8.8.8', '-c', '4']).then(code => console.log(`Error Code: ${code}`)); 

這所承諾的基礎,所以你可以鏈接多個命令。它甚至與child_process.spawn功能簽名兼容,所以它應該是你使用它的任何地方的替代品。

3

這裏是最乾淨的方法,我已經找到了:如果

require("child_process").spawn('bash', ['./script.sh'], { 
    cwd: process.cwd(), 
    detached: true, 
    stdio: "inherit" 
});