Files

212 lines
5.4 KiB
Bash
Executable File

#!/bin/bash
convert_to_bytes() {
local val="$1"
local num unit int frac mul result
# trim whitespace
val="${val#"${val%%[![:space:]]*}"}"
val="${val%"${val##*[![:space:]]}"}"
# empty input -> 0
[[ -z "$val" ]] && echo 0 && return
# check if numeric (optional decimal + unit)
if [[ ! $val =~ ^[0-9]+([.][0-9]+)?[KMGTkmgT]?$ ]]; then
echo 0
return
fi
# separate number and unit
num="${val%[KMGTkmgT]}"
unit="${val#$num}"
# handle decimals
if [[ "$num" == *.* ]]; then
int="${num%%.*}"
frac="${num#*.}"
frac="${frac}000"
frac="${frac:0:3}"
else
int="$num"
frac="0"
fi
# multiplier
case "${unit^^}" in
K) mul=1024 ;;
M) mul=$((1024*1024)) ;;
G) mul=$((1024*1024*1024)) ;;
T) mul=$((1024*1024*1024*1024)) ;;
*) mul=1 ;;
esac
# use base 10 for all arithmetic to avoid octal errors
result=$((10#$int * mul + 10#$frac * mul / 1000))
echo "$result"
}
function ensure_comma() {
if [[ $FIRST -eq 1 ]]
then
FIRST=
else
echo -n ,
fi
}
FSPATH="/mnt"
PARSER_STATE=0
while IFS= read -r line; do
case $PARSER_STATE in
0)
if [[ $line =~ ^Filesystem:[[:space:]]+([^[:space:]]+)$ ]]
then
uuid="${BASH_REMATCH[1]}"
elif [[ $line == Data\ type* ]]
then
PARSER_STATE=1
elif [[ $line == "Compression:" ]]
then
#echo -n "bcachefs_compression,fspath=$FSPATH,uuid=$uuid "
FIRST=1
PARSER_STATE=2
elif [[ $line == "Btree usage:" ]]
then
echo -n "bcachefs_btree_usage,fspath=$FSPATH,uuid=$uuid "
FIRST=1
PARSER_STATE=3
elif [[ $line =~ ^Pending\ reconcile: ]]
then
echo -n "bcachefs_reconcile,fspath=$FSPATH,uuid=$uuid "
FIRST=1
PARSER_STATE=4
REMAINING=(replicas checksum erasure_code compression target high_priority pending)
elif [[ $line =~ ^([^ ]+)\ \(device\ ([0-9]+)\):[[:space:]]+([^[:space:]]+)[[:space:]]+([^[:space:]]+)[[:space:]]+([0-9]+)%$ ]]
then
echo -n "bcachefs_devices,fspath=$FSPATH,uuid=$uuid,label=${BASH_REMATCH[1]},devid=${BASH_REMATCH[2]},device=${BASH_REMATCH[3]} mode=\"${BASH_REMATCH[4]}\",usage=${BASH_REMATCH[5]}"
PARSER_STATE=5
#else
#echo unknown?
fi
;;
1)
if [[ "$line" == "" ]]
then
PARSER_STATE=0
fi
;;
2)
if [[ "$line" == "" ]]
then
#echo
PARSER_STATE=0
elif [[ $line =~ ^([^[:space:]]+)[[:space:]]*(.*)$ ]]
then
field="${BASH_REMATCH[1]// /_}"
rest="${BASH_REMATCH[2]}"
read -r val1 val2 val3 <<<"$rest"
val1="$(convert_to_bytes "$val1")"
#ensure_comma
#echo -n "${field}_compressed=$val1"
if [[ ! -z "$val2" ]]
then
val2="$(convert_to_bytes "$val2")"
#echo -n ",${field}_uncompressed=$val2"
fi
if [[ ! -z "$val3" ]]
then
val3="$(convert_to_bytes "$val3")"
#echo -n ",${field}_avgextsize=$val3"
fi
#else
#echo unknown?
fi
;;
3)
if [[ "$line" == "" ]]
then
echo
PARSER_STATE=0
elif [[ $line =~ ^([^:]+)[:space:]+(.*)$ ]]
then
field="${BASH_REMATCH[1]// /_}"
val="${BASH_REMATCH[2]}"
val="$(convert_to_bytes "$val")"
ensure_comma
echo -n "$field=$val"
#else
#echo unknown?
fi
;;
4)
if [[ "$line" == "" ]]
then
for field in "${REMAINING[@]}"
do
ensure_comma
echo -n "${field}_data=0,${field}_metadata=0"
done
echo
PARSER_STATE=0
elif [[ $line =~ ^([^:]+):[[:space:]]*(.*)$ ]]
then
field="${BASH_REMATCH[1]// /_}"
rest="${BASH_REMATCH[2]}"
read -r val1 val2 <<<"$rest"
val1="$(convert_to_bytes "$val1")"
val2="$(convert_to_bytes "$val2")"
ensure_comma
echo -n "${field}_data=$val1,${field}_metadata=$val2"
REMAINING=( "${REMAINING[@]/$field}" )
#else
#echo unknown?
fi
;;
5)
if [[ "$line" == "" ]]
then
echo
PARSER_STATE=0
elif [[ $line =~ ^[[:space:]]*([^:]+):[[:space:]]*(.*)$ ]]
then
field="${BASH_REMATCH[1]// /_}"
rest="${BASH_REMATCH[2]}"
read -r val1 val2 val3 <<<"$rest"
val1="$(convert_to_bytes "$val1")"
echo -n ",${field}_data=$val1"
if [[ ! -z "$val2" ]]
then
echo -n ",${field}_buckets=$val2"
fi
if [[ ! -z "$val3" ]]
then
val3="$(convert_to_bytes "$val3")"
echo -n ",${field}_fragmented=$val3"
fi
#else
#echo unknown?
fi
;;
esac
#if [[ $PARSER_STATE -ne 1 ]]
#then
# echo "Got line: $line"
#fi
done < <(sudo bcachefs fs usage -a "$FSPATH")