12

I guess the question is, could I somehow calculate the CPU utilization percentage just by reading the /proc/stat once?

# head -1 /proc/stat
cpu  67891300 39035 6949171 2849641614 118251644 365498 2341854 0

I am thinking about summarizing the columns except the IOWait (I was reading somewhere that it is counted in the idle) and that would give me the 100% and each individual column could be turned into percentage by (column/100_percent)*100.

  • user: normal processes executing in user mode
  • nice: niced processes executing in user mode
  • system: processes executing in kernel mode
  • idle: twiddling thumbs
  • iowait: waiting for I/O to complete
  • irq: servicing interrupts
  • softirq: servicing softirqs
  • steal: involuntary wait
  • guest: running a normal guest
  • guest_nice: running a niced guest

Is this a viable approach or i am totally off the track?

4 Answers 4

11

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.

6
+50

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

4
  • How do you parse the data?
    – ewwhite
    Jan 7, 2014 at 2:19
  • @ewwhite -> I edited my answer to show how I parse the data. Jan 7, 2014 at 2:42
  • Beautiful graphs! Regarding your missing column annotation: askubuntu.com/a/120961/451886. If it's running in a VM, maybe it's the "steal" counter.
    – rkagerer
    Sep 19, 2015 at 21:22
  • +1 for rrdtool and ramdisk!
    – Shadi
    Aug 15, 2019 at 3:06
4

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.

0

Or if you're happy with just two digits after the point awk can do it all a lot simpler and more readable:

 awk -v oldidle=$(awk '/cpu / {print $5}' /proc/stat; sleep 1) '/cpu / {perc=100-($5-oldidle)/100 ; printf "%s", perc}' /proc/stat

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.