-
Notifications
You must be signed in to change notification settings - Fork 0
/
cpuplot
263 lines (219 loc) · 7.01 KB
/
cpuplot
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
#!/bin/sh
#################################################
# Command Line profiler of CPU usage.
#
# Displays bar graphs to the terminal depicting the Total CPU Usage Percentage
# and the Total 1 Minute Load Average Percentage. It also shows the process
# with the highest CPU utilization.
#
# Default sleep interval between readings is 5secs. But a different one can be
# passed as an argument in the command line.
#
#
# Developer: Ismael Antadillas
# BSD 3-Clause License
# Default values
SECS=5
WIDTH="medium"
echo
#################################################
# Find System type
unameOut="$(uname -s)"
case "${unameOut}" in
Linux*) ENV=Linux;;
Darwin*) ENV=Mac;;
CYGWIN*) ENV=Cygwin;;
MINGW*) ENV=MinGw;;
*) ENV="UNKNOWN:${unameOut}"
esac
#################################################
# Usage function
function usage () {
cat <<EOF
Usage: $0 -i [seconds] -w [small medium large xlarge]
where:
-i interval time in seconds between CPU readings.
-w width of the output, "small", "medium", "large", "xlarge"
As described in the man page for the "ps" command:
"The CPU utilization of the process is a decaying average over up to a
minute of previous (real) time. Because the time base over which this
is computed varies (some processes may be very young), it is possible
for the sum of all %cpu fields to exceed 100%."
Because of the above some values for the "Total CPU Usage" may be over 100%.
When this happens, the bar plot will be truncated to 100%.
The 1 minute Load Average Percentage, is calculated dividing the 1 minute
Load Average by the number of Cores in the system.
EOF
echo
exit 0
}
#################################################
# Handling Options
while getopts ":w:i:" opt; do
case $opt in
w)
if [ "$OPTARG" == "small" ] ; then
WIDTH="$OPTARG"
elif [ "$OPTARG" == "medium" ] ; then
WIDTH="$OPTARG"
elif [ "$OPTARG" == "large" ] ; then
WIDTH="$OPTARG"
elif [ "$OPTARG" == "xlarge" ] ; then
WIDTH="$OPTARG"
else
echo "Invalid argument for width option '-w'. Usage example: cpuplot -w medium" >&2
usage
fi
;;
i)
re='^[0-9]+([.][0-9]+)?$'
if ! [[ $OPTARG =~ $re ]] ; then
#Value is not a number or is empty.
echo "Invalid argument for interval option '-i'. Usage example: cpuplot -i 5" >&2
usage
else
SECS=$OPTARG
fi
;;
\?)
echo "Invalid option: -$OPTARG" >&2
usage
;;
:)
echo "Option -$OPTARG requires an argument." >&2
usage
;;
esac
done
#################################################
#Create and print header.
if [ "$ENV" == "Mac" ] ; then
HARDWARE=$(system_profiler SPHardwareDataType)
CORES=$( printf "%s" "$HARDWARE" | grep Cores: | cut -d' ' -f11)
RAM=$( printf "%s" "$HARDWARE" | grep Memory: )
RAM=$(echo "${RAM#*'Memory: '}")
else
CORES=$(nproc --all)
RAM=$(free -m | grep Mem: | awk '{print $2;}')
RAM="$RAM MB"
fi
HOST=$(hostname)
USER=$(whoami)
ZONE=$(date +"%Z")
SLEEP_SPAN=$((SECS + 1)) #SLEEP_SPAN is the value to check if the system was in "sleep mode".
echo "Hostname: $HOST"
echo "User: $USER | Interval: $SECS secs"
echo "ENV: $ENV | RAM: $RAM | Cores: $CORES | Timezone: $ZONE"
echo
#################################################
#Create colums labels string
HEADER=""
if [ "$WIDTH" == "small" ] ; then
HEADER="0....1....2....3....4....5....6....7....8....9....1"
elif [ "$WIDTH" == "medium" ] ; then
HEADER="TIME COMMAND %CPUt 0....1....2....3....4....5....6....7....8....9....1"
elif [ "$WIDTH" == "large" ] ; then
HEADER="TIME PID PROCESS %MEMp %MEMt %LA1m %CPUp |%CPUt 0....1....2....3....4....5....6....7....8....9....1"
elif [ "$WIDTH" == "xlarge" ] ; then
HEADER="TIME PID PROCESS %MEMp %MEMt %CPUp |%CPUt 0....1....2....3....4....5....6....7....8....9....1 |%LA1m 0....1....2....3....4....5....6....|....8....9....1"
fi
#################################################
#Do until "Ctrl-c".
# Disable user typing into the terminal. It honors "Ctrl-D".
stty -echo
while true
do
DATETIME=$(date +"%Y-%m-%d %T")
LOADS=$(uptime)
LOADS=$(echo "${LOADS#*": "}")
echo "$DATETIME Load Avg: $LOADS"
echo "$HEADER"
#################################################
#Do 22 times, so it fits in the default 24 lines of a terminal screen.
for (( i=1; i<=22; i++))
do
START_TIME=$SECONDS
#Parse the command with most cpu usage.
if [ "$ENV" == "Mac" ] ; then
#OUTSTR=$(ps -Arco %cpu= -o pmem= -o pid= -o comm=)
OUTSTR=$(ps -erc -o pcpu=,pmem=,pid=,comm=)
OUTSTR="${OUTSTR:1}" #del first char. Macos bash has one extra space in front.
else
OUTSTR=$(ps -e -o pcpu=,pmem=,pid=,comm= --sort -pcpu)
fi
###############################
# Calculate 1 minute Load Average %
if [ "$WIDTH" == "large" ] || [ "$WIDTH" == "xlarge" ] ; then
LOAD1m=$(uptime)
LOAD1m=$(echo "${LOAD1m#*": "}" | cut -d' ' -f1)
LOADHALFp=$(awk -v a=$LOAD1m -v b=$CORES 'BEGIN { print int((a / b) * 50) }')
LOAD1mROUNDEDp=$(($LOADHALFp * 2))
if [ $LOADHALFp -gt 50 ] ; then
LOADHALFp=50
fi
fi
###############################
# Extract other values
PSFIRSTLINE=($(printf "$OUTSTR" | head -n 1))
CMDNAME=$(echo "$OUTSTR" | head -n 1 | cut -c 17-28)
CMDCPU=$(echo "${PSFIRSTLINE[0]}")
CMDMEM=$(echo "${PSFIRSTLINE[1]}")
PID=$(echo "${PSFIRSTLINE[2]}")
TOTALS=$(printf "$OUTSTR" | awk '{cpu += $1; mem += $2} END {print cpu " " mem}')
TIME=$(date +%T)
MEMTOTAL=$(printf "%s" "$TOTALS" | cut -d' ' -f2)
CPUTOTAL=$(printf "%s" "$TOTALS" | cut -d' ' -f1)
CPUROUNDED=$(printf "%.0f" $CPUTOTAL)
#Truncate if greater than 100%
if [ $CPUROUNDED -gt 100 ] ; then
CPUROUNDED=100
fi
CPUDIV=$(expr $CPUROUNDED / 2)
###############################
# Print values based on -w
if [ "$WIDTH" == "medium" ] ; then
printf "%s %-12s %-5s " "$TIME" "$CMDNAME" "$CPUTOTAL"
elif [ "$WIDTH" == "large" ] ; then
printf "%s %-5s %-12s %-5s %-5s %-5s %-5s %s%-5s " "$TIME" "$PID" "$CMDNAME" "$CMDMEM" "$MEMTOTAL" "$LOAD1mROUNDEDp" "$CMDCPU" "|" "$CPUTOTAL"
elif [ "$WIDTH" == "xlarge" ] ; then
printf "%s %-5s %-12s %-5s %-5s %-5s %s%-5s " "$TIME" "$PID" "$CMDNAME" "$CMDMEM" "$MEMTOTAL" "$CMDCPU" "|" "$CPUTOTAL"
fi
##################################
#Print Total CPU% bar
BARCHAR="|"
BARSTRING=""
for (( count=0; count<=$CPUDIV; count++))
do
BARSTRING+=$BARCHAR
done
printf "%-52s" "$BARSTRING"
##################################
#Print 1 minute Load Average Percentage bar
if [ "$WIDTH" == "xlarge" ] ; then
printf "%s%-5s " "|" "$LOAD1mROUNDEDp"
BARCHAR="|"
BARSTRING=""
for (( count=0; count<=$LOADHALFp; count++)) ; do
if [ $count -eq 35 ] ; then
BARCHAR="+"
fi
BARSTRING+=$BARCHAR
done
printf "%-51s" "$BARSTRING"
fi
echo
sleep $SECS
#Find if the system has been asleep.
ELAPSED_TIME=$(($SECONDS - $START_TIME))
if [ "$ELAPSED_TIME" -gt "$SLEEP_SPAN" ] ; then
echo
echo
echo "ASLEEP"
i=23 #So it exits to the main loop and prints the scale bars.
break
fi
#22 lines loop done
done # for loop
#infinite loop done
done #while true
stty echo #enable keyboard input