228 lines
7.8 KiB
Bash
228 lines
7.8 KiB
Bash
#!/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
|