Me gustaría convertir la salida ZFS de "10.9T" a bytes reales, usando algo en una línea o dos, en lugar de ejecutar funciones matemáticas genéricas y condiciones para T
,,, etc. ¿Existe una manera eficiente de hacer esto G
? M
?
Por ahora tengo algo como esto:
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
Esto produce un error: no se puede ejecutar la expresión en 10.9T
o 50G
porque no son números.
¿Existe alguna bash
función conocida para esto?
También me gusta la conveniencia de especificarlo como lo hice en la MINFREE
var en la parte superior. Entonces, una manera fácil de convertir sería buena.
Estees lo que esperaba evitar (presentando argumentos para cada letra), aunque el guión parece limpio.
Editar: ¡Gracias por todos los comentarios! Aquí está el código que tengo ahora. , partes relevantes al menos;
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
Respuesta1
No existe una buena manera de convertir zfs
los números legibles por humanos en bytes reales. Los números legibles por humanos están redondeados y, por lo tanto, son inexactos.
Si desea números exactos, use la -p
opción (analizable por máquina) y la salida será en bytes, que podrá analizar y formatear como desee.
$ 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
Pero zfs
no es posible analizar la salida legible por humanos y convertirla a números "exactos". Dado que los números legibles por humanos solo se especifican en (digamos) tres cifras significativas, su extrapolación "exacta" también será precisa solo en tres cifras.
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
Respuesta2
Puedes usarnumfmt
(en Debian y derivados forma parte, coreutils
por lo que ya debería estar allí):
numfmt - Convierte números de/a cadenas legibles por humanos
$ numfmt --from=iec-i 50.1Gi
53794465383
también puede leer el valor de stdin
$ echo "50.1Gi" | numfmt --from=iec-i
53794465383
Tenga cuidado, tiene en cuenta la configuración regional del separador decimal.
Respuesta3
zpool list
Puede proporcionar los números en bytes. por ejemplo, enumerar tres grupos (15T, 29T y 416G) en mi servidor zfs principal.
Primero, sin -H
y -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%
Y de nuevo, con -H
y-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
La salida está separada por tabulaciones, por lo que se procesa fácilmente con awk
o cut
o lo que quieras (incluso un ciclo shell while read si lo deseas).insistir). El capacity
campo es el porcentaje utilizado, por lo que es particularmente útil si desea enviar una alerta por correo electrónico si un grupo está por debajo del 10 % o 20 % gratuito.
-H
esScripted mode. Do not display headers, and separate fields by a single tab instead of arbitrary space.
-p
imprime un formato "analizable" en lugar de "legible por humanos" (es decir, bytes)
Por cierto, las versiones recientes de ZFS tienen las páginas de manual zfs
y zpool
divididas en páginas separadas para sus subcomandos, propiedades, conceptos, etc. Si eso es lo que está ejecutando, consulte las páginas de manual para zpool-list
obtener zpoolprops
más detalles. De lo contrario, simplemente man zpool
.
Respuesta4
Como está etiquetado y redactado, bash
lo incluyo por diversión.
Sin validación. (Es decir, si la unidad existe, etc.)
Cantidad base SI 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
Cantidad base IEC 1024 (2^10) (usando 2 decimales)
Máx. 81.914P (64 bits) (8.191 si usa 3 decimales, etc.)
#!/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