-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPrintAggregateCPUUsagePercent
More file actions
executable file
·118 lines (105 loc) · 4.28 KB
/
PrintAggregateCPUUsagePercent
File metadata and controls
executable file
·118 lines (105 loc) · 4.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#!/usr/bin/env bash
# vim:set ft=shell nowrap et sta shiftwidth=4 ts=8 sts=0
#
#############
## Purpose ##
#############
#
# Parse /proc/stat for aggregate cpu usage and report it in %
#
###############
## Reference ##
###############
#
# https://stackoverflow.com/questions/23367857/accurate-calculation-of-cpu-usage-given-in-percentage-in-linux
#
# https://man7.org/linux/man-pages/man5/proc.5.html
#
# https://www.kernel.org/doc/Documentation/filesystems/proc.txt
#
set -hu
PrintAggregateCPUUsagePercent() {
local bash_only=1 # 1=[use only bash arithmatic) 0=[use bc]
local printf_scale=1 # If bc is used, how many decimal places to show
local printf_minwidth=3 # Minimum width for printf field, padded with leading spaces (NOTE GNU printf does not support min width modifier for %s)
local bc_scale=$(( printf_scale + 1 )) # bc_scale must be one higher than printf_scale for rounding (NOTE bash only truncates instead of rounding)
local num_samples=4 # total_avg = tally / ( num_samples - 1 )
local sample_period_seconds="0.25" # Time in seconds to sleep between iterations
local print_newline=1 # 1=[Print a newline after n%] 0=[Do not print a newline after n%]
local tally=0 # Cumulative average
local total_avg=0 # Final cumulative average divided by number of samples
local idle=0
local prev_idle=0
local busy=0
local total=0
local prev_total=0
local delta_total=0
local delta_idle=0
local label=''
local usage_percent=0
local usage_percent=0
local user=0
local nice=0
local system=0
local idle=0
local iowait=0
local irq=0
local softirq=0
local steal=0
local xtra=''
(( num_samples < 1 )) && num_samples=1 # num_samples must be > 0
for (( i=0; i <= ( num_samples + 1 ); i++ )); do
while IFS=' ' read -r label user nice system idle iowait irq softirq steal xtra; do
case $label in
(cpu)
idle=$(( idle + iowait ))
busy=$(( user + nice + system + irq + softirq + steal ))
total=$(( idle + busy ))
delta_total=$(( total - prev_total ))
delta_idle=$(( idle - prev_idle ))
# Skip the first iteration
(( i )) && {
if (( bash_only )); then
usage_percent=$(( (delta_total - delta_idle) * 100 / delta_total ))
(( i > 1 )) && tally=$(( tally + usage_percent ))
elif (( ! bash_only )); then
usage_percent=$( bc -l <<< "scale=$bc_scale; (($delta_total - $delta_idle) *100) / $delta_total" )
(( i > 1 )) && tally=$( bc -l <<< "scale=$bc_scale; ($tally + $usage_percent)" )
fi
}
#(( i > 1 )) && echo "($((i-1))) usage: $usage_percent tally: $tally" # For debug and double-checking results
prev_idle=$idle
prev_total=$total
sleep "$sample_period_seconds"s
;;
esac
done < /proc/stat
done
(( i == ( num_samples + 2 ) )) && {
if (( bash_only )); then
total_avg=$(( tally / num_samples ))
if (( total_avg )); then
if (( print_newline )); then
echo "${total_avg}%"
elif (( ! print_newline )); then
printf '%s' "${total_avg}%"
fi
else
if (( print_newline )); then
echo "<1%"
elif (( ! print_newline )); then
printf '%s' "<1%"
fi
fi
elif (( ! bash_only )); then
total_avg=$( bc -l <<< "scale=$bc_scale; ($tally / $num_samples)" )
total_avg=$( printf "%${printf_minwidth}.${printf_scale}f" "$total_avg" )
if (( print_newline )); then
echo "${total_avg/%.0}%"
elif (( ! print_newline )); then
printf '%s' "${total_avg/%.0}%"
fi
fi
}
}
PrintAggregateCPUUsagePercent