MOTDfetch/motdfetch.d/03-filesystem

228 lines
7.8 KiB
Plaintext
Raw Normal View History

2023-02-07 10:10:46 +01:00
#!/usr/bin/env bash
#
# status of mounted filesystems in 2 steps
# 1. use "df" for general fs except zfs, squashfs, tmpfs, devtmpfs and overlay
# 2. use "zpool" for ZFS pools
# + displays name, filesystem type, used blocks and inodes or pool health when relevant
# + custom warn threshold for blocks
# + warn threshold for inodes (80%), flashing danger threshold for health, blocks (95%) and inodes (90%)
#
# requirements: sudo apt install coreutils
# optionnal: sudo apt install zfsutils-linux
# GENERAL ###########################################################
# locale env
unset LC_ALL
export LC_MESSAGES=C
# check if module was disabled
module_disable=${module_filesystem_disable:=0}
if (($module_disable == 1)); then
exit 1
fi
# colors
c_txt=${c_txt:="39"}
c_txt_emphase=${c_txt_emphase:="35"}
c_txt_deco=${c_txt_deco:="97"}
c_txt_invert=${c_txt_invert:="30"}
c_bg=${c_bg_sec:="47"}
c_danger=${c_danger:="31"}
c_warning=${c_warning:="33"}
c_success=${c_success:="32"}
c_title=${c_title:="${c_bg};1;${c_txt_invert}m"}
# OPTIONS ###########################################################
# max usage warning threshold
max_usage=${module_filesystem_max_usage:="85"}
# disable ZFS section
zfs_disable=${module_filesystem_zfs_disable:=0}
# PREPARATIONS ######################################################
# disk usage: ignore zfs, squashfs & tmpfs, standard error output because of a bug with /run/user/1000/doc
dfcmd=$(/usr/bin/df -H -x zfs -x squashfs -x tmpfs -x devtmpfs -x overlay --output 2>/dev/null)
mapfile -t dfoutput < <(echo "$dfcmd" | tail -n+2)
# determine best width for the bar
largesttarget=$(echo "$dfcmd" | awk '{if (length ($12)>max) max=length($12)} END {print max}')
if [[ $((largesttarget+30)) -gt 50 ]]; then
bar_width=$((largesttarget+30))
else
bar_width="50"
fi
# OUTPUT ############################################################
# general filesystems
linecounter=0
if [[ "${dfoutput[@]}" ]]; then
# output header
echo -e "\n\e[${c_title} Filesystem usage \e[0m\n"
# output filesystem status except ZFS
for line in "${dfoutput[@]}"; do
# parse df output
diskid=$(echo "$line" | awk '{print $12}')
diskused=$(echo "$line" | awk '{print $10}'| sed 's/%//')
disktotal=$(echo "$line" | awk '{print $7}')
fsformat=$(echo "$line" | awk '{print $2}')
inodesused=$(echo "$line" | awk '{print $6}'| sed 's/%//')
inodestotal=$(echo "$line" | awk '{print $3}')
# bar & blocks coloration, danger red above 95%
if [[ "${diskused}" -ge "95" ]]; then
barcolor="\e[1;${c_danger}m"
blockscolor="\e[1;${c_danger}m"
flashing="\e[5m"
elif [ "${diskused}" -ge "${max_usage}" ]; then
barcolor="\e[1;${c_warning}m"
blockscolor="\e[1;${c_warning}m"
flashing=""
else
barcolor="\e[1;${c_success}m"
blockscolor="\e[${c_txt}m"
flashing=""
fi
# print colored bar until used_width
used_width=$(((diskused*$bar_width)/100))
bar="[${barcolor}"
for ((i=0; i<$used_width; i++)); do
bar+="="
done
# print dimmmed bar until end
bar+="\e[${c_txt}m\e[0m"
for ((i=$used_width; i<$bar_width; i++)); do
bar+="="
done
bar+="\e[0m]"
# print blocks usage line & bar
padding=$((bar_width-28))
if [[ $linecounter -ge 1 ]]
then
echo -e "\n"
fi
echo "${line}" | printf "\e[1;${c_txt_emphase}m%-${padding}s\e[0m${blockscolor}%+3s%% used ${flashing}blocks\e[0m out of %+4s\n" $diskid $diskused $disktotal | sed 's/^/ /'
echo -e "${bar}" | sed 's/^/ /'
# print filesystem type & inodes usage line
if [[ ! "$inodesused" == "-" ]]
then
padding=$((bar_width-34))
# inodes coloration, danger red above 90%
if [[ "${inodesused}" -ge "90" ]]; then
inodescolor="\e[1;${c_danger}m"
flashing="\e[5m"
elif [[ "${inodesused}" -ge "80" ]]; then
inodescolor="\e[1;${c_warning}m"
flashing=""
else
inodescolor="\e[${c_txt}m"
flashing=""
fi
echo "${line}" | printf "Type: %-${padding}s${inodescolor}%+3s%% used ${flashing}inodes\e[0m out of %+4s\n" $fsformat $inodesused $inodestotal | sed 's/^/ /'
else
echo "${line}" | printf "Type: %-10s\n" $fsformat | sed 's/^/ /'
fi
linecounter=$((linecounter+1))
done
else
echo " no general filesystem available, ZFS expected in next section"
fi
# check if ZFS section was disabled
if [[ $zfs_disable == 1 ]]; then
exit 1
fi
# output ZFS header
echo -e "\n\e[${c_title} Zpool usage \e[0m\n"
# check if zpool is available
if ! command -v zpool 1> /dev/null; then
echo " no ZFS tools available"
exit 1
fi
# ZFS zpool usage & health status
zlistcmd=$(zpool list -o name,cap,size,health 2> /dev/null)
if [[ $zlistcmd == "no pools available" ]]; then
echo " no ZFS pool available"
else
mapfile -t zpools < <(echo "$zlistcmd" | tail -n+2)
# determine best width for the bar
largesttarget=$(echo "zlistcmd" | awk '{if (length ($1)>max) max=length($1)} END {print max}')
if [[ $((largesttarget+30)) -gt 50 ]]; then
bar_width=$((largesttarget+30))
else
bar_width="50"
fi
linecounter=0
for line in "${zpools[@]}"; do
# parse zpool list output
poolid=$(echo "$line" | awk '{print $1}')
poolused=$(echo "$line" | awk '{print $2}'| sed 's/%//')
pooltotal=$(echo "$line" | awk '{print $3}')
poolhealth=$(echo "$line" | awk '{print $4}')
# bar & pools coloration, danger red above 95%
if [[ "${poolused}" -ge "95" ]]; then
barcolor="\e[1;${c_danger}m"
poolscolor="\e[1;${c_danger}m"
flashing="\e[5m"
elif [[ "${poolused}" -ge "${max_usage}" ]]; then
barcolor="\e[1;${c_warning}m"
poolscolor="\e[1;${c_warning}m"
flashing=""
else
barcolor="\e[1;${c_success}m"
poolscolor="\e[${c_txt}m"
flashing=""
fi
# print colored bar until used_width
used_width=$(((poolused*$bar_width)/100))
bar="[${barcolor}"
for ((i=0; i<$used_width; i++)); do
bar+="="
done
# print dimmmed bar until end
bar+="\e[${c_txt}m\e[0m"
for ((i=$used_width; i<$bar_width; i++)); do
bar+="="
done
bar+="\e[0m]"
# print pool usage line & bar
padding=$((bar_width-29))
if [[ $linecounter -ge 1 ]]
then
echo -e "\n"
fi
echo "${line}" | printf "\e[1;${c_txt_emphase}m%-${padding}s\e[0m${poolscolor}%+3s%% used ${flashing}blocks\e[0m out of %+5s\n" $poolid $poolused $pooltotal | sed 's/^/ /'
echo -e "${bar}" | sed 's/^/ /'
# print pool health line
padding=$((bar_width-34))
# health coloration, danger red for FAULTED
if [[ "${poolhealth}" == "FAULTED" ]]; then
healthcolor="\e[1;${c_danger}m"
flashing="\e[5m"
elif [[ "${poolhealth}" == "OFFLINE" ]] || [[ "${poolhealth}" == "UNAVAIL" ]] || [[ "${poolhealth}" == "REMOVED" ]] || [[ "${poolhealth}" == "DEGRADED" ]]; then
healthcolor="\e[1;${c_warning}m"
flashing=""
else
healthcolor="\e[${c_txt}m"
flashing=""
fi
padding=$((bar_width-17))
text="health"
echo "${line}" | printf "%+${padding}s status: ${healthcolor}${flashing}%+8s\e[0m\n" $text ${poolhealth,,} | sed 's/^/ /'
linecounter=$((linecounter+1))
done
fi