Is there a way to calculate the percentage CPU utilization by reading /proc/stat at once?

You are on the right track, top uses this file for this purpose. But you need to read it more than once.

Utilization is a is a measure of use over time. You can read it once providing you know the uptime in seconds of the host, then divide by that, but that would give you a utility rate of the host since the machine was booted.

If you want a rate over 5 seconds, you would read the file once, sleep for 5 seconds, read it again, obtain the difference of the calculations and divide by 5.


Your approach is correct. You can use /proc/stat as raw data and feed for example rrdtool with it. I've done myself something like this so I know 100% it is possible. You can nicely then graph the whole system load or each core individually.

Here is a working example of my own: enter image description here

Reassuming -> You can do it, it is not hard just basic mathematics and my graphs are a live example of that. For collecting data I do a snapshot of /proc/stat to a temporary file localted on ramdisk and then I parse that file to collect data every 1 minute.

how I parse the data (fragment of bash script):

cat=/bin/cat # others defined the same way
......

$cat /proc/stat > /ramdisk/tmp/stat

ssCpuRawUser=`$cat /ramdisk/tmp/stat|$grep "cpu " | $awk '{print $2}'`
ssCpuRawNice=`$cat /ramdisk/tmp/stat|$grep "cpu " | $awk '{print $3}'`
    #other columns follow ....... 

#the most important there is that it is an incrementing COUNTER.
if [ ! -f ${data_dir}/sys.cpu.rrd ];then
        $rrdtool create ${data_dir}/sys.cpu.rrd -s 60 \
        DS:ssCpuRawUser:COUNTER:300:0:1250000 \
        DS:ssCpuRawNice:COUNTER:300:0:1250000 \
        DS:ssCpuRawSystem:COUNTER:300:0:1250000 \
        DS:ssCpuRawIdle:COUNTER:300:0:1250000 \
        DS:ssCpuRawIOwait:COUNTER:300:0:1250000 \
        DS:ssCpuRawIRQ:COUNTER:300:0:1250000 \
        DS:ssCpuRawSoftIRQ:COUNTER:300:0:1250000 \
            RRA:AVERAGE:0.5:1:532800

fi

$rrdtool update ${data_dir}/sys.cpu.rrd N:$ssCpuRawUser:$ssCpuRawNice:$ssCpuRawSystem:$ssCpuRawIdle:$ssCpuRawIOwait:$ssCpuRawIRQ:$ssCpuRawSoftIRQ

# then in a loop each core the same way until all are parsed.

after You get data into the rrd database You can graph and sky is the limit :) http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html


If you want oneliner it may looks like this:

echo $(echo '100'; echo $(echo '(';head -1 /proc/stat | awk '{print $5}'; sleep 1; echo '-';head -1 /proc/stat |  awk '{print $5}';echo ')/100') | bc -l) | bc -l

The result: 97.17000000000000000000

How it works:

echo $(echo '(';head -1 /proc/stat | awk '{print $5}'; sleep 1; echo '-';head -1 /proc/stat |  awk '{print $5}';echo ')/100')

produces ( 1055057784 - 1055058055 )/100 then this line feed to bc. Will have something like -7.84000000000000000000, then just wrap it up to 100-$(value) and feed to bc again

There: sleep # - 1 second delay, if you change this value then the intermediate result should be divided to the number of seconds. $5 - 5th field, according to man proc and http://www.linuxhowtos.org/System/procstat.htm

Please let me know if this doesn't work for you.