Ich möchte die ZFS-Ausgabe von „10,9 T“ mithilfe von ein oder zwei Zeilen in tatsächliche Bytes umwandeln, anstatt allgemeine mathematische Funktionen und If-Bedingungen für T
, G
, M
, usw. auszuführen. Gibt es eine effiziente Möglichkeit, dies zu tun?
Im Moment habe ich so etwas:
MINFREE="50G"
POOLSIZE=`zpool list $POOLNAME -o size` #Size 10.9T
POOLSIZE=$(echo "$POOLSIZE" | grep -e [[:digit:))] #10.9T
POOLFREE=500M #as an example
let p=POOLSIZE x=POOLFREE y=MINFREE z=POOLSIZE;
CALC=$(expr "echo $((x / y))")
if [ "${CALC}" < 1 ]; then
# we are less than our min free space
echo alert
fi
Dies führt zu einem Fehler: Der Ausdruck kann nicht ausgeführt werden 10.9T
, oder 50G
weil es sich nicht um Zahlen handelt.
Gibt es bash
hierfür eine bekannte Funktion?
Mir gefällt auch die praktische Möglichkeit, es anzugeben, wie ich es dort MINFREE
oben in der Variable getan habe. Eine einfache Möglichkeit zur Konvertierung wäre also schön.
Dasist das, was ich vermeiden wollte (einen Fall für jeden Buchstaben anzugeben), das Skript sieht jedoch sauber aus.
Bearbeiten: Danke für alle Kommentare! Hier ist der Code, den ich jetzt habe. Zumindest die relevanten Teile;
POOLNAME=san
INFORMAT=auto
#tip; specify in Gi, Ti, etc.. (optional)
MINFREE=500Gi
OUTFORMAT=iec
NOW=`date`;
LOGPATH=/var/log/zfs/zcheck.log
BOLD=$(tput bold)
BRED=${txtbld}$(tput setaf 1)
BGREEN=${txtbld}$(tput setaf 2)
BYELLOW=${txtbld}$(tput setaf 3)
TXTRESET=$(tput sgr0);
# ZFS Freespace check
#poolsize, how large is it
POOLSIZE=$(zpool list $POOLNAME -o size -p)
POOLSIZE=$(echo "$POOLSIZE" | grep -e [[:digit:]])
POOLSIZE=$(numfmt --from=iec $POOLSIZE)
#echo poolsize $POOLSIZE
#poolfree, how much free space left
POOLFREE=`zpool list $POOLNAME -o free`
#POOLFREE=$(echo "$POOLFREE" | grep -e [[:digit:]]*.[[:digit:]].)
POOLFREE=$(echo "$POOLFREE" | grep -e [[:digit:]])
POOLFREE=$(numfmt --from=$INFORMAT $POOLFREE)
#echo poolfree $POOLFREE
#grep -e "vault..[[:digit:]]*.[[:digit:]].")
#minfree, how low can we go, before alerting
MINFREE=$(numfmt --from=iec-i $MINFREE)
#echo minfree $MINFREE
#FORMATTED DATA USED FOR DISPLAYING THINGS
#echo formattiing sizes:
F_POOLSIZE=$(numfmt --from=$INFORMAT --to=$OUTFORMAT $POOLSIZE)
F_POOLFREE=$(numfmt --from=$INFORMAT --to=$OUTFORMAT $POOLFREE)
F_MINFREE=$(numfmt --from=$INFORMAT --to=$OUTFORMAT $MINFREE)
F_MINFREE=$(numfmt --from=$INFORMAT --to=$OUTFORMAT $MINFREE)
#echo
printf "${BGREEN}$F_POOLSIZE - current pool size"
printf "\n$F_MINFREE - mininium freespace allowed/as specified"
# OPERATE/CALCULATE SPACE TEST
#echo ... calculating specs, please wait..
#let f=$POOLFREE m=$MINFREE x=m/f;
declare -i x=$POOLFREE/$MINFREE;
# will be 0 if has reached low threshold, if poolfree/minfree
#echo $x
#IF_CALC=$(numfmt --to=iec-i $CALC)
if ! [ "${x}" == 1 ]; then
#printf "\n${BRED}ALERT! POOL FREESPACE is low! ($F_POOLFREE)"
printf "\n${BRED}$F_POOLFREE ${BYELLOW}- current freespace! ${BRED}(ALERT!}${BYELLOW} Is below your preset threshold!";
echo
else
printf "\nPOOLFREE - ${BGREEN}$F_POOLFREE${TXTRESET}- current freespace";
#sleep 3
fi
Antwort1
Es gibt keine gute Möglichkeit, die für Menschen lesbaren Zahlen in tatsächliche Bytes umzuwandeln zfs
. Die für Menschen lesbaren Zahlen sind gerundet und daher ungenau.
Wenn Sie genaue Zahlen wünschen, verwenden Sie die -p
Option (maschinenanalysierbar). Die Ausgabe erfolgt in Bytes, die Sie beliebig analysieren und formatieren können.
$ zfs list tank/var; zfs list -p tank/var
NAME USED AVAIL REFER MOUNTPOINT
tank/var 8.33G 387G 6.90G /var
NAME USED AVAIL REFER MOUNTPOINT
tank/var 8948584448 415137447936 7407120384 /var
Es ist jedoch zfs
nicht möglich, die für Menschen lesbare Ausgabe zu analysieren und in „exakte“ Zahlen umzuwandeln. Da die für Menschen lesbaren Zahlen nur auf (sagen wir) drei signifikante Stellen spezifiziert sind, wird Ihre „exakte“ Extrapolation auch nur auf drei Stellen genau sein.
TiB=$((2**40))
GiB=$((2**30))
# MINFREE=$((50*$TiB)) # 50 TiB
MINFREE=$((50*$GiB)) # 50 GiB
POOLFREE=$(zpool list -Hpo free "$POOLNAME") #Free in bytes
if [ "$POOLFREE" -lt "$MINFREE" ]; then
printf "alert\n"
else
printf "no alert -- %d bytes free >= %d byte minimum\n" "$POOLFREE" "$MINFREE"
fi
Antwort2
Sie könnennumfmt
(in Debian und Derivaten ist es Teil davon, coreutils
also sollte es bereits vorhanden sein):
numfmt - Konvertiert Zahlen von/in menschenlesbare Zeichenfolgen
$ numfmt --from=iec-i 50.1Gi
53794465383
es kann auch den Wert von stdin lesen
$ echo "50.1Gi" | numfmt --from=iec-i
53794465383
Seien Sie vorsichtig, es berücksichtigt das Gebietsschema für das Dezimaltrennzeichen.
Antwort3
zpool list
kann die Zahlen in Bytes angeben. z. B. Auflistung von drei Pools (15T, 29T und 416G) auf meinem Haupt-ZFS-Server.
Erstens ohne -H
und -p
:
$ zpool list -o name,size,alloc,free,capacity
NAME SIZE ALLOC FREE CAP
backup 14.5T 6.15T 8.40T 42%
export 29T 17.8T 11.2T 61%
ganesh 416G 169G 247G 40%
Und wieder mit -H
und-p
$ zpool list -H -p -o name,size,alloc,free,capacity
backup 15994458210304 6763872280576 9230585929728 42
export 31885837205504 19592775573504 12293061632000 61
ganesh 446676598784 181604904960 265071693824 40
Die Ausgabe ist durch Tabulatoren getrennt, sodass sie leicht mit awk
oder cut
oder was auch immer Sie möchten verarbeitet werden kann (sogar eine Shell-while-read-Schleife, wenn Siepochen). Das capacity
Feld gibt den verwendeten Prozentsatz an und ist daher besonders nützlich, wenn Sie eine E-Mail-Benachrichtigung senden möchten, wenn ein Pool weniger als 10 % oder 20 % frei ist.
-H
IstScripted mode. Do not display headers, and separate fields by a single tab instead of arbitrary space.
-p
druckt „analysierbares“ im Gegensatz zum „menschenlesbaren“ Format (d. h. Bytes)
Übrigens sind in neueren Versionen von ZFS die Manpages zfs
und zpool
in separate Seiten für ihre Unterbefehle, Eigenschaften, Konzepte usw. aufgeteilt. Wenn Sie das verwenden, finden Sie weitere Einzelheiten in den Manpages für zpool-list
und zpoolprops
. Andernfalls einfach man zpool
.
Antwort4
bash
Da es mit „Ich werfe es zum Spaß ein“ getaggt und formuliert ist .
Keine Validierung. (D. h. ob Einheit vorhanden ist usw.)
SI-Basisgröße 1000 (10^3):
#!/bin/bash
declare -A s=([Y]=24 [Z]=21 [E]=18 [P]=15 [T]=12 [G]=9 [M]=6 [K]=3)
input="$1"
suffix="${input: -1}"
number="${input:0: -1}"
printf "%.0f bytes\n" "${number}e+${s[$suffix]}"
$ ./bashsize10 1.6T
1600000000000 bytes
$ ./bashsize10 3681.914Y
3681914000000000000130023424 bytes
IEC-Basisgröße 1024 (2^10) (mit 2 Dezimalstellen)
Max. 81,914P (64-Bit) (8,191 bei Verwendung von 3 Dezimalstellen usw.)
#!/bin/bash
declare -A s=([P]=50 [T]=40 [G]=30 [M]=20 [K]=10)
input="$1"
suffix="${input: -1}"
number="${input:0: -1}"
d=$(printf "%.0f" "${number}e+2")
printf "%d bytes\n" "$(( d * 2 ** s["$suffix"] / 100 ))"
$ ./bashsize2 1.6T
1759218604441 bytes