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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .