# To calculate the total CPU usage as a percentage

I have been developing the below method to calculate the CPU usage of a Linux system at a point in time, as a percentage of the total number of cores available in the system.

#!/bin/bash

# Get number of cores from proc cpuinfo
CORECOUNT=grep -c ^processor /proc/cpuinfo
# Use top, skip the first 7 rows, count the sum of the values in column 9 - the CPU column, do some simple rounding at the end.
CPUUSAGE=top -bn 1 | awk 'NR>7{s+=$9} END {print s/'$CORECOUNT'}' | awk '{print int($1+0.5)}' printf "$CPUUSAGE\n"


Would this be considered a reasonably accurate way of doing this? Any suggestions to increase efficiency/accuracy would be greatly appreciated.

• PS. good for you in figuring in the # cores...ala "Irix" cpu timekeeping... which helps know # of cores and multithreading. I.e. if a process only ever uses 100% cpu, it is likely 1 thread; if >100%, likely more than one thread. Doesn't equate 50%cpu on a single core machine with 50% on a 12 core (like many windows utils do). – Astara Sep 9 '14 at 19:04

There are a few problems you have here. The first, is the concept of getting the usage at a point in time, which is not possible. But, you can get it for a span of time. You are using top -bn 1 which will get the usage for the span of a second.

Since you are accessing the /proc system to get the number of CPU's, you may as well use the right /proc file for what you want:

cat /proc/stat:

 ~ $cat /proc/stat cpu 177206 161827 1274669 3582291272 144435 154779 0 0 0 0 cpu0 32170 48533 914773 894903107 30650 69784 0 0 0 0 cpu1 52790 41088 180295 895685563 76035 14410 0 0 0 0 cpu2 18745 40955 49422 895959636 11295 2234 0 0 0 0 cpu3 73500 31249 130178 895742965 26454 68350 0 0 0 0 intr 339571688 48 10 0 0 0 0 2 0 1 0 0 0 152 0 0 8750527 0 322394 40428015 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...... 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ctxt 660707018 btime 1401123121 processes 196075 procs_running 1 procs_blocked 0 softirq 322202763 0 136092603 1792784 40737199 4701209 0 6 133008518 51951 5818493  With the above file, I would calculate it manually.... (also using the documentation here: http://www.mjmwired.net/kernel/Documentation/filesystems/proc.txt#1212 ) I have taken the liberty of programming it myself.... since the recommendation is sucha deviation from your solution, it makes sense: #!/bin/bash #CORECOUNT=$(grep cpu /proc/stat | grep -v 'cpu ' | wc -l)
#echo $CORECOUNT cores not needed for calculation though DELAY=${1:-1}

function getstat() {
grep 'cpu ' /proc/stat | sed -e 's/  */x/g' -e 's/^cpux//'
}

function extract() {
echo $1 | cut -d 'x' -f$2
}

function change() {
local e=$(extract$ENDSTAT $1) local b=$(extract $STARTSTAT$1)
local diff=$(($e - $b )) echo$diff
}

#Record the start statistics

STARTSTAT=$(getstat) sleep$DELAY

#Record the end statistics

ENDSTAT=$(getstat) #http://www.mjmwired.net/kernel/Documentation/filesystems/proc.txt#1236 #echo "From$STARTSTAT"
#echo "TO   $ENDSTAT" # usr nice sys idle iowait irq guest #From 177834 168085 1276260 3584351494 144468 154895 0 0 0 0 #TO 177834 168085 1276261 3584351895 144468 154895 0 0 0 0 USR=$(change 1)
SYS=$(change 3) IDLE=$(change 4)
IOW=$(change 5) #echo USR$USR SYS $SYS IDLE$IDLE IOW $IOW ACTIVE=$(( $USR +$SYS + $IOW )) TOTAL=$(($ACTIVE +$IDLE))
PCT=$(($ACTIVE * 100 / $TOTAL )) echo "BUSY$ACTIVE TOTAL $TOTAL$PCT %"

• Nice! If you post that code for code review, maybe I can improve on it a bit ;-) – janos Sep 9 '14 at 15:19
• @janos - good idea, and done – rolfl Sep 9 '14 at 15:33

Let's assume that column 9 in the output of the top command is a good measure of the CPU usage. I don't really know, but let's assume.

Your script could be written cleaner and better:

1. Don't use ... style process substitution, use $(...) instead 2. Usually, there's no point piping the output of one awk command to another. You can do what you did in a single awk, which is better, because you save one unnecessary process 3. Better to pass variables to awk using the -v parameter than trying to embed in the command line 4. Don't use printf when an echo is enough and simpler 5. Avoid extremely long lines. The mouse wheel scrolls up-down fine, left-right is a PITA. You could break that long comment to 2 lines. Suggested implementation: #!/bin/bash # Get number of cores CORECOUNT=$(grep -c ^processor /proc/cpuinfo)
# Use top, skip the first 7 rows, count the sum of the values
#   in column 9 - the CPU column, do some simple rounding at the end
CPUUSAGE=$(top -bn 1 | awk -v n=$CORECOUNT 'NR > 7 { s += $9 } END { print int(s / n + .5); }') echo$CPUUSAGE


Btw, do you really need $CPUUSAGE? If not, just omit the variable, change the last line: top -bn 1 | awk -v n=$CORECOUNT 'NR > 7 { s += \$9 } END { print int(s / n + .5); }'


(I used n as the Awk variable name mainly to make my answer fit on the page without scrolling ;-) Feel free to name it corecount or as you like.)

• Re: comment #4 above -- echo is not portable. printf is the posix recommended way of printing for portability (primarily because of echo's behavior with expanding inline codes ("\n") w/r/t the -e/-E switches and how it works with suppressing newlines (-n), and whether or not -- suppresses further argument processing... I.e. those items aren't the same everywhere... so printf ended up getting the standards vote. (I probably more often use echo...) – Astara Sep 9 '14 at 18:57
• I know. I wouldn't recommend echo for anything involving any of its switches, they are a complete mess. But in this particular case, using printf just for a simple printing with a newline, that's just tedious. – janos Sep 9 '14 at 19:05