如何用 node.js 获取目标进程的 CPU 占用率

前言

本脚本仅仅在 linux 上方便使用,请大家注意,先不废话,上脚本。

代码

/*
测试程序
while( true ){
    a = exports.getProcessCPUUsage( [ 2882, 10388 ], oldProcessTock )
    oldProcessTock = a.processTick;
    // rate += parseFloat( a.rate );
    count++;
    if( count % 100000 == 0 ){
        console.log( `${count} ${rate}` )
        console.log( Date.now() )
        count = 0;
        rate = 0;
    }
}

平均每秒该方法可以操作
    21579.628830384117 次
测试平台
    Intel(R) Core(TM) i7-7500U CPU @ 2.70GHz

*/

var fs = require( 'fs' );
var os = require( 'os' );

var CPUCoreNumbers = os.cpus().length;

var CPUTikHistory = null;
exports.getProcessCPUUsage = ( pid, oldProcessTick, sysTickPerSec ) => {
    // let ProcessStat = fs.readFileSync( `/proc/${process.pid}/stat`, 'utf8' );

    var ProcessTickSum = 0;
    if( Array.isArray( pid ) ){
        pid.forEach( p => {
            let ProcessStat = fs.readFileSync( `/proc/${p}/stat`, 'utf8' );
            let ProcessStatArr = ProcessStat.match( /(\w+)+/g )
            if( ProcessStatArr == null ) return null;
            ProcessTickSum += parseInt( ProcessStatArr[13] ) + parseInt( ProcessStatArr[14] );
        } )
    }else{
        let ProcessStat = fs.readFileSync( `/proc/${pid}/stat`, 'utf8' );
        let ProcessStatArr = ProcessStat.match( /(\w+)+/g )
        if( ProcessStatArr == null ) return null;
        ProcessTickSum = parseInt( ProcessStatArr[13] ) + parseInt( ProcessStatArr[14] );
    }

    let TikSum = 0;
    if( sysTickPerSec == null ){
        let CPUStat = fs.readFileSync( '/proc/stat', 'utf8' );
        let MatchLine = CPUStat.match(/(.*)\n/);
        if( MatchLine == null ){
            console.error( "This function not match this machain, please take care" );
            process.exit();
        }
        let CPULineArr = MatchLine[1].match( /(\w+)+/g );
        // console.log( CPULineArr )
        if( CPULineArr[0] != 'cpu' ){
            console.error( "This function not match this machain, please take care" );
            process.exit();
        }
        CPULineArr.forEach( (num) => {
            let i = parseInt( num );
            if( isNaN( i ) ) return;
            TikSum += parseInt(num);
        } )
        if( CPUTikHistory == null ){
            CPUTikHistory = TikSum;
        }
    }

    if( ( oldProcessTick == null ) || ( oldProcessTick == 0 ) ){
        if( sysTickPerSec == null ){
            return {
                rate: 0.00,
                processTick: ProcessTickSum,
                sysTick: TikSum,
            }
        }else{
            return {
                rate: 0.00,
                processTick: ProcessTickSum,
            }
        }
    }

    if( sysTickPerSec == null ){
        DiffSysTick = TikSum - CPUTikHistory;
        CPUTikHistory = TikSum;
        if( DiffSysTick == 0 ){
            return {
                rate: 0,
                processTick: ProcessTickSum,
                sysTick: TikSum,
            }
        }
        let rate = ( ProcessTickSum - oldProcessTick )*100/DiffSysTick*CPUCoreNumbers
        return {
            rate: rate.toFixed(2),
            processTick: ProcessTickSum,
            sysTick: TikSum,
        }
    }else{
        let rate = ( ProcessTickSum - oldProcessTick )*100/sysTickPerSec*CPUCoreNumbers;

        return {
            rate: rate.toFixed(2),
            processTick: ProcessTickSum,
        }
    }
}

//==============================================================================
// let oldProcessTock = 0;
// setInterval( ()=>{
//
//     a = exports.getProcessCPUUsage( [ 2882, 10388 ], oldProcessTock )
//     console.log( a );
//     oldProcessTock = a.processTick;
//
// }, 1000 );

说明

getProcessCPUUsage 函数接受三个参数,前两个是必选的,第三个是可选的
pid
    代表想查询程序的 pid, 如果想查询自己的,可用 proceess.pid 获取,
    如果想合并查询几个进程共同的 CPU 占用率,可以用数组包含各个进程的 PID

oldProcessTick
    为上一次的进程的 Tick, 如果是第一次则设置为 0,
    在运行完本函数后会返回当下指定进程的所有 Tick, 之后可以下一次使用

sysTickPerSec
    如果你知道当前系统的一秒内的固定 Tick,你可以从这个参数传进来,这样减少该函数的运算所需的资源
    如果你不知道,不设置即可,该函数会自动算出两次调用该函数时间段内的总 Tick

返回有三个参数
rate
    CPU 占用率,单位为 xx.xx%, 保留两位小树

processTick
    指定进程当前 Tick 之和

sysTick
    当前系统的总 Tick
    当你指定 sysTickPerSec 则无此字段

注意
1. 这里返回的 CPU 占用率是只两次调用之间的 CPU 占用率,如果你不是严格的按照每秒调用一次该函数, CPU 占用率会和 Top 显示的不一样。
2. 如果你的硬件平台不只一个 CPU,而且你是按照每秒调用一次,而且你想获取进程的 CPU 占用率特别高,那么此时此处的 CPU 占用率会超过 100%
posted @ 2020-03-21 22:06  Mojies  阅读(3680)  评论(0编辑  收藏  举报