iT邦幫忙

11

node beyond server (parallel del/rmdir)

node.js原本就提供了許多像是檔案系統操作、Binary資料處理的核心模組,在0.6.x之後又引進了cluster,可以產生多個子行程。其實要快速做一些工具也蠻好用的...

前一陣子對公司產品做一些壓力測試,有一個困擾是,測試完後會產生大量的暫存檔(每次大概有2GB),刪除檔案的速度很慢...查了一下,系統好像沒有內建可以多工刪檔的工具XD,既然手邊有node.js,乾脆自己動手
因為我的需求只是把某目錄中的所有子目錄刪光,所以就寫了簡單的程式,一古腦把目錄中的子目錄殺光:

var cluster = require('cluster');
var numCPUs = require('os').cpus().length;
var fs = require('fs');

if (cluster.isMaster) {
    var dir = [];
    
    //get the dir for processing... it means all
    fs.readdir('.', function(err, files) {
        if(err) process.exit();
        for(var i=0; i<files.length; i++) {
            var stat = fs.statSync(files[i]);
            if(stat.isDirectory()) dir.push(files[i]);
        }
        for (var i = 0; i < numCPUs; i++) {
            var worker = cluster.fork();
            //if worker feedback that mission completed, then tell them what next to do
            worker.on('message', function(msg) {
                if(dir.length>0) {
                    this.send({complete: false, dir: dir.shift()});
                } else {
                    this.send({complete: true});
                }
            });
        }
    });
    //if workers died, then restart them
    cluster.on('death', function(worker) {
        if (dir.length>0) {
            var worker = cluster.fork();
            //if worker feedback that mission completed, then tell them what next to do
            worker.on('message', function(msg) {
                if(dir.length>0) {
                    this.send({complete: false, dir: dir.shift()});
                } else {
                    this.send({complete: true});
                }
            });
        }
    });
} else {
    var start = false;

    function timeoutHandler() {
        if(start) {
            console.log('worker exit.');
            process.exit();
        } else {
            setTimeout(timeoutHandler, 100);
        }
    }
    console.log('worker started.');
    process.on('message', function(msg) {
        console.log('worker got message, id:'+msg.dir);
        if(msg.complete) {
            start = msg.complete;
        } else {
            var cp = require('child_process');
            cp.exec('del /s /q '+msg.dir, function(err) {
                if(!err) {
                    cp.exec('rmdir /s /q '+msg.dir, function(err) {
                        process.send({});
                    });
                } else {
                    process.send({});
                }
            });
        }
    });
    setTimeout(timeoutHandler, 100);
    process.send({});//tell master that i'm ready...
}

這個程式的構造,直接參考:http://nodejs.org/api/cluster.html

工作方式:

  1. master: 透過fs模組,取得要刪除的目錄清單
  2. master: 依照作業系統核心數目,產生worker
  3. worker: 第一次執行,會先告訴master: I'm ready.
  4. master: 如果有目錄未刪除,就交給I'm ready的worker執行
  5. worker: 建立子行程,呼叫系統命令del以及rmdir來刪除檔案及目錄
  6. worker: 回報master事情做完了
  7. master: 如果還有沒刪的,就叫worker繼續刪;不然就叫worker結束執行

刪檔的速度比起單純用gui或是在conaole下呼叫del/rmdir快了不少,只是偶爾會出現目錄沒殺到XD,可能是檔案沒殺完就去殺目錄?不過再執行一次就會殺光,所以懶得改...

基本上,node.js可用的模組已經上萬,所以不要把自己侷限在伺服器端,他也是個可以很快上手的工具。

(PS. 這只是自己用的工具,請不要任意拿到任意目錄中執行,他不會做判斷的...另外,del/rmdir是windows console中的命令,拿到其他作業系統無效的)


1 則留言

0
逮丸逮丸
iT邦大師 1 級 ‧ 2012-04-18 18:32:57

看到可以指定不同的CPU來工作,
問個題外話,
在Linux上是否有什麼工具,
可以讓所執行的程式,指定在哪個CPU跑嗎?

剛才問到答案,才知道有 taskset 這個東西。

我要留言

立即登入留言