1#!/bin/sh 2 3# This script displays the per-cpu utilization values. 4# The utilization value is fetched from the cpufreq driver with the file: 5# /sys/devices/system/cpu/cpu%d/cpufreq/cpu_utilization 6# The utilization value in this file is the cpu utilization scaled to the max CPU frequency. 7# So, this script converts this value to the current utilization levels. 8# 9# USAGE: cpuutil [-i <interval>] [-n <samples>] [-m <mask>] 10# 11 12help() 13{ 14 echo "USAGE: cpuutil [-i <interval>] [-n <samples>] [-m <mask>]" 15 printf "\n" 16 echo " i - Specifies the interval between two sucessive polls in seconds" 17 echo " Default: 1 second" 18 echo " n - Specifies the total number of samples to be polled" 19 echo " Default: No limit. User must terminate with ctrl-c" 20 echo " m - Specifies the CPU mask. Must be prefixed with '0x'" 21 echo " Default: All CPUs" 22 echo "" 23 echo " E.g. cpuutil -i 10 -n 5 -m 0x2" 24 echo " Display utilization of CPU1 every 10 seconds, 5 times" 25} 26 27usage() 28{ 29 echo "Error: Invalid usage! Option: $1" 30 printf "\n" 31 help 32 exit 1 33} 34 35# The the total number of CPUs 36getMaxCpuCount() 37{ 38 local val 39 val=`cat /proc/cpuinfo | grep processor | tail -1 | awk '{print $3}'` 40 echo $((val + 1)) 41} 42 43# Get the CPU Mask for all CPUs 44getAllCpuMask() 45{ 46 local val="" 47 local i=0 48 local max=$(getMaxCpuCount) 49 local shiftval 50 51 while [ $i -lt $max ]; 52 do 53 shiftval=1 54 shiftval=$((shiftval << $i)) 55 val=$((val | shiftval)) 56 i=$((i + 1)) 57 done 58 59 echo $val 60} 61 62# Get mask for specific CPU 63getCpuMask() 64{ 65 local shiftval=1 66 echo $((shiftval << $1)) 67} 68 69# Poll and display values 70pollValues() 71{ 72 local i=0 73 local utilfile="/sys/devices/system/cpu/cpu%d/cpufreq/cpu_utilization" 74 local curfreqfile="/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_cur_freq" 75 local maxfreqfile="/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq" 76 local util 77 local curfreq 78 local maxfreq 79 local fname 80 local val 81 local tmp 82 83 printf "%8s" "." 84 85 while [ $i -lt $(getMaxCpuCount) ];do 86 if [ $(( cmask & $(getCpuMask $i) )) != 0 ]; then 87 fname=$(printf $utilfile $i) 88 util=`cat $fname` 89 90 fname=$(printf $curfreqfile $i) 91 curfreq=`cat $fname` 92 93 fname=$(printf $maxfreqfile $i) 94 maxfreq=`cat $fname` 95 96 val=$(( $((util * maxfreq)) / curfreq)) 97 printf "%8d" $val 98 eval avg$i=\$\(\(\ avg$i\ \+\ val\ \)\) 99 fi 100 if [ $i = 0 ]; then 101 avgcount=$((avgcount + 1)) 102 fi 103 i=$((i + 1)) 104 done 105 106 printf "\n" 107 108 sleep $1 109} 110 111# Display the average values 112showAvg() 113{ 114 local i=0 115 local tmp 116 local rem 117 118 printf "\n\n%8s" "Avg:" 119 120 while [ $i -lt $(getMaxCpuCount) ];do 121 if [ $((cmask & $(getCpuMask $i) )) != 0 ]; then 122 eval tmp=\$avg$i 123 rem=`expr $tmp % $avgcount` 124 if [ $rem -gt $((avgcount / 2)) ]; then 125 tmp=$((tmp + avgcount)) 126 fi 127 tmp=$((tmp / avgcount)) 128 printf "%8d" $tmp 129 fi 130 i=$((i + 1)) 131 done 132 133 printf "\n" 134} 135 136# ctrl-c handler 137sigHandler() 138{ 139 showAvg 140 exit 0 141} 142 143avgcount=0 144echo "/-------------------------------------------------------------------------------------\\" 145echo "| This script uses the values exported by the cpufreq driver via the sys interface. |" 146echo "| And values exported by the cpufreq driver are scaled by the driver to |" 147echo "| 'utilization at max-freq'. This script converts these values to current utilization |" 148echo "| levels using the current CPU frequency. So please expect some loss in accuracy due |" 149echo "| to rounding off occuring twice. |" 150echo "\\-------------------------------------------------------------------------------------/" 151printf "\n" 152 153# Parse the command line arguments 154for i in "$@"; do 155 case $i in 156 -i) 157 if [ -n "$currarg" ]; then 158 usage $currarg 159 fi 160 currarg="-i" 161 ;; 162 -n) 163 if [ -n "$currarg" ]; then 164 usage $currarg 165 fi 166 currarg="-n" 167 ;; 168 -m) 169 if [ -n "$currarg" ]; then 170 usage $currarg 171 fi 172 currarg="-m" 173 ;; 174 -h|--help) 175 if [ -n "$currarg" ]; then 176 usage $currarg 177 fi 178 help 179 exit 0 180 ;; 181 *) 182 if [ "$currarg" = "-i" -o "$currarg" = "-n" ]; then 183 parameter=`echo $i | sed 's/[0-9]*//'` 184 if [ -n "$parameter" ]; then 185 usage $currarg 186 else 187 if [ "$currarg" = "-i" ]; then 188 pinterval=$i 189 else 190 maxsamples=$i 191 fi 192 currarg="" 193 fi 194 elif [ "$currarg" = "-m" ]; then 195 parameter=`echo $i | sed 's/0[xX][0-9]*//'` 196 if [ -n "$parameter" ]; then 197 usage $currarg 198 else 199 cmask=`echo $i | sed 's/0[xX]//'` 200 currarg="" 201 fi 202 else 203 usage $i 204 fi 205 ;; 206 esac 207done 208 209# Set default values if no arguments are specified 210if [ -z $pinterval ]; then 211 pinterval=1 212elif [ $pinterval -gt 3600 ];then 213 echo "Limiting polling interval to 1 hour" 214 pinterval=3600 215fi 216if [ -z $maxsamples ]; then 217 maxsamples=0 218fi 219 220 221if [ -z "$cmask" ]; then 222 cmask=$(getAllCpuMask) 223else 224 allcpumask=$(getAllCpuMask) 225 maskresult=$((cmask & ~allcpumask)) 226 if [ $maskresult != 0 ]; then 227 echo "Error: Invalid CPU Mask" 228 printf "Total CPUs is: %d, Mask for all CPUs is 0x%x\n" $(getMaxCpuCount) $(getAllCpuMask) 229 exit 1 230 fi 231fi 232 233# Display the actual values 234printf "\n" 235echo "Polling interval: $pinterval seconds" 236if [ $maxsamples = 0 ];then 237 echo "Max Samples: 0 (No limit set)" 238else 239 echo "Max Samples: $maxsamples" 240fi 241printf "CPU Mask: 0x%x\n" $cmask 242printf "\n" 243 244i=0 245printf "%8s" "CPU:" 246while [ $i -lt $(getMaxCpuCount) ]; do 247 if [ $((cmask & $(getCpuMask $i) )) != 0 ]; then 248 printf "%8d" $i 249 fi 250 eval avg$i=0 251 i=$((i + 1)) 252done 253printf "\n" 254 255trap sigHandler INT 256 257if [ $maxsamples -eq 0 ];then 258 while [ 1 ]; do 259 pollValues $pinterval 260 done 261else 262 while [ $maxsamples -ne 1 ]; do 263 pollValues $pinterval 264 maxsamples=$((maxsamples - 1)) 265 done 266 267 # We dont want to sleep after the last poll 268 pollValues 0 269 showAvg 270fi 271 272exit 0 273