Wie lassen sich menschenlesbare Größen effizient in Bytemengen umrechnen?

Wie lassen sich menschenlesbare Größen effizient in Bytemengen umrechnen?

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 50Gweil es sich nicht um Zahlen handelt.

Gibt es bashhierfür eine bekannte Funktion?

Mir gefällt auch die praktische Möglichkeit, es anzugeben, wie ich es dort MINFREEoben 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 -pOption (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 zfsnicht 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, coreutilsalso 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 listkann die Zahlen in Bytes angeben. z. B. Auflistung von drei Pools (15T, 29T und 416G) auf meinem Haupt-ZFS-Server.

Erstens ohne -Hund -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 -Hund-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 awkoder cutoder was auch immer Sie möchten verarbeitet werden kann (sogar eine Shell-while-read-Schleife, wenn Siepochen). Das capacityFeld 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.

  • -HIstScripted mode. Do not display headers, and separate fields by a single tab instead of arbitrary space.
  • -pdruckt „analysierbares“ im Gegensatz zum „menschenlesbaren“ Format (d. h. Bytes)

Übrigens sind in neueren Versionen von ZFS die Manpages zfsund zpoolin separate Seiten für ihre Unterbefehle, Eigenschaften, Konzepte usw. aufgeteilt. Wenn Sie das verwenden, finden Sie weitere Einzelheiten in den Manpages für zpool-listund zpoolprops. Andernfalls einfach man zpool.

Antwort4

bashDa 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

verwandte Informationen