Files
_dotfiles/.config/i3blocks/cpu_util_detailed/cpu_util_detailed
2024-06-12 13:49:42 +02:00

101 lines
3.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# cpu_util_detailed
# Meant for usage as an i3blocks blocklet.
# It reports detailed CPU utilization in colors using pango markup.
# Written by skidnik <skidnik@gmail.com>
# Licensed under GPLv3 https://www.gnu.org/licenses/gpl-3.0.txt
#
# Defaults if not set
interval=${interval:-0} # just in case it's started not by i3blocks
stats=${stats:-usr nice sys iowait}
format=${format:-%6.2f}
warn=${warn:-80}
declare -A colormap=(
[usr]=${usr_color:-green}
[nice]=${nice_color:-yellow}
[sys]=${sys_color:-red}
[iowait]=${iowait_color:-grey}
[irq]=${irq_color:-purple}
[soft]=${soft_color:-violet}
[steal]=${steal_color:-orange}
[guest]=${guest_color:-cyan}
[gnice]=${gnice_color:-blue}
[idle]=${idle_color:-white}
[total]=${total_color:-white}
)
# If $report_time not set:
# Set it to $interval - 1, but not less than 1.
# If $interval is 'repeat' or -2 set report_time to 5.
if [[ -z $report_time ]]; then
if [[ "$interval" =~ ^-?[0-9]+$ ]];
then
if [[ $interval -gt 2 ]]; then
report_time=$(( interval - 1 ))
elif [[ $interval == -2 ]]; then
report_time=5
else
report_time=1
fi
elif [[ $interval == repeat ]]; then
report_time=5
fi
fi
# 'idle' is hardcoded as it's always required, no need to ask for it two times.
getstats=${stats//idle /}
# Get detailed CPU load as a set of variables with same names:
if _mpstat="$(command -v mpstat)"
then
declare $( ${_mpstat} -u "$report_time" 1 | sed -n '3,4p' | awk -v stats="$getstats idle" '
BEGIN{
split(stats, fields)
}
{
split($0, headers)
getline
split($0, values)
for (i in fields) {
for (j in headers)
if ( headers[j] ~ "^%" fields[i] ) {
printf "%s=%s\n", fields[i], values[j]
}
}
}
')
total=$( bc <<<"scale=2; 100 - $idle" )
else
# This is a fallback way for the case `mpstat` is not available
start_uptime=($(cat /proc/uptime))
start=($(sed -n '1p' /proc/stat))
sleep ${report_time}
end_uptime=($(cat /proc/uptime))
end=($(sed -n '1p' /proc/stat))
user_hz=$(getconf CLK_TCK)
num_cpus=$(nproc --all)
delta_time=$( bc <<<"scale=2; ${end_uptime[0]}-${start_uptime[0]}" )
user_hz_time=$( bc <<<"$delta_time * $user_hz" )
usr=$( bc <<<"scale=4; (${end[1]}-${start[1]})/$num_cpus/$user_hz_time*100" )
nice=$( bc <<<"scale=4; (${end[2]}-${start[2]})/$num_cpus/$user_hz_time*100" )
sys=$( bc <<<"scale=4; (${end[3]}-${start[3]})/$num_cpus/$user_hz_time*100" )
idle=$( bc <<<"scale=4; (${end[4]}-${start[4]})/$num_cpus/$user_hz_time*100" )
iowait=$( bc <<<"scale=4; (${end[5]}-${start[5]})/$num_cpus/$user_hz_time*100" )
irq=$( bc <<<"scale=4; (${end[6]}-${start[6]})/$num_cpus/$user_hz_time*100" )
soft=$( bc <<<"scale=4; (${end[7]}-${start[7]})/$num_cpus/$user_hz_time*100" )
steal=$( bc <<<"scale=4; (${end[8]}-${start[8]})/$num_cpus/$user_hz_time*100" )
guest=$( bc <<<"scale=4; (${end[9]}-${start[9]})/$num_cpus/$user_hz_time*100" )
gnice=$( bc <<<"scale=4; (${end[10]}-${start[10]})/$num_cpus/$user_hz_time*100" )
total=$( bc <<<"scale=4; ${end_uptime[1]}-${start_uptime[1]}" )
fi
# Output stats with pango formatting in a defined order
for stat in $stats
do
# No other way to make format adjustable
# shellcheck disable=SC2059
printf "<span color='%s'>$format</span>" "${colormap[$stat]}" "${!stat}"
done
echo # trailing newline
# Short text
# shellcheck disable=SC2059
printf "$format\n" "$total"
# Set urgent flag if over warn threshold
(( $( bc <<<"$total >= $warn" ) )) && exit 33 || :