1.20.2014
用 node.js 跑 shell script
張貼者:
Jean Pan
於
星期一, 1月 20, 2014
怎麼用 node.js 跑 shell script 咧 ?
node child_process module 主要提供了四個 create child process 的 function
1. exec
2. spawn
3. fork
4. execFile
這邊我就只介紹 exec & spawn
然後一點點 fork …
spawn 是最原始的 create child process function,其他三個都是 spawn 的封裝
spawn 和 exec 的最大差別是
1. 帶入的參數不同 ( exec 比較靈活 )
2. 和 parent process 之間 io 處理上不同 ( 請參考 http://villadora-blog.herokuapp.com/2013/05/07/differences-between-exec-and-spawn/ 這邊就不多提 ~ )
直接來看程式碼
var cp = require('child_process'),
//spawn = cp.spawn,
exec = cp.exec,
//ls = spawn('ls', ['-lh', '/usr']);
ls = exec('ls -lh /usr');
ls.stdout.on('data', function(data) {
console.log('stdout: ' + data);
});
ls.on('close', function(code) {
console.log('child process exited with code' + code);
});
fork 的話是可以直接執行 node.js 的程式
像是 fork('fork_child.js');
而他和 spawn 的差別是 fork 可以會在 parent 和 child process 間建立一個 IPC ( Inter-process communication ) 用來做溝通
直接來看程式碼
fork_parent.js
var cp = require('child_process'),
child = cp.fork('fork_child.js');
// spawn('node', ['fork_child.js']);
child.on('message', function(message) {
console.log('parent got a message from child: ', message);
});
child.send('Call me Daddy');
fork_child.js
var cp = require('child_process');
process.on('message', function(message) {
console.log('child got a message from parent: ', message);
});
process.send('Daddy ~~~~~~~~~~');
然後這次我在 project 中會用到 node.js 的 child process module 是因為我要執行 shell 去掃所有的字串
shell command 長這樣 :
execStr = 'grep -R --exclude-dir={lang,yrb,node_modules,compilers,sprites,uitests,tools,assets,tests} "' + str + '" ' + path + ' >> str.txt';
其實就是讀一個 yrb.json 檔然後掃 string 去 grep 然後輸出到某個 file
現在知道可用 child_process module 來寫 shell script
簡單啦 ~
我就寫一個 for 迴圈把 yrb.json 的每一個 string 讀出來再去做 grep
但是 !!
遇到了一個問題 …
出現了這樣的 error
node.js:201 throw e; // process.nextTick error, or error event on first tick
^ Error: spawn EMFILE
at errnoException (child_process.js:481:11)
at ChildProcess.spawn (child_process.js:444:11)
at child_process.js:342:9
at Object.execFile (child_process.js:252:15)
at child_process.js:220:18
我就用 google 大神找解法
先是找到了
1. 設定 ulimit -n 10000 ( 什麼是 ulimit http://homeserver.com.tw/2011/04/02/ulimit/ )
但不行 !!! 在我的 dev 最多就只能調到 1000 … ( 可能是硬體的限制吧 … )
然後就找到了另一個解法
2. queue
nodejs 是 non-blocking … 所以其實會去同時執行多個 process 這樣就會把資源給吃光光 …
所以只好寫一個似 blocking 的方法來解決
var queue = [],
MAX = 20, // only allow 20 simultaneous exec calls
count = 0, // holds how many execs are running
keywords = […]; // long list of urls // our callback for each exec call
function callback(err, stdout, stderr) {
count -= 1;
if (queue.length > 0 && count < MAX) { // get next item in the queue! count += 1;
var url = queue.shift();
exec('shell command', wget_callback);
}
}
keywords.forEach( function(url) {
if (count < MAX) {
// go get the file!
count += 1;
exec('shell command', wget_callback);
} else {
// queue it up…
queue.push(url);
}
});
這樣就可以解決一次跑太多 process 把資源吃光光的問題了 !
資料參考:
https://www.byvoid.com/blog/node-child-process-ipc/
http://homeserver.com.tw/2011/04/02/ulimit/
http://www.runtime-era.com/2012/10/quick-and-dirty-nodejs-exec-limit-queue.html
訂閱:
張貼留言 (Atom)




沒有留言:
張貼留言