人間が読めるサイズをバイト数に変換する効率的な方法は何ですか?

人間が読めるサイズをバイト数に変換する効率的な方法は何ですか?

一般的な数学関数や、、などTの条件を実行するのではなく、1 行または 2 行の何かを使用して、ZFS 出力の「10.9T」を実際のバイトに変換したいと思います。これを効率的に行う方法はありますか?GM

今のところ、次のようなものがあります:

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

これにより、エラーが発生します: 、 または は数値ではないため10.9T、に対して式を実行できません。50G

bashこれには既知の機能がありますか?

上部の varで行ったように指定する便利さも気に入っていますMINFREE。そのため、変換する簡単な方法があると便利です。

これこれは私が避けたかったことですが(各文字を大文字にする)、スクリプトはきれいに見えます。

編集: コメントをありがとうございます! これが今私が持っているコードです。少なくとも関連部分です。

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

答え1

zfsの人間が判読できる数値を実際のバイトに変換する良い方法はありません。人間が判読できる数値は四捨五入されているため、不正確です。

正確な数値が必要な場合は、-pオプション (machine parseable) を使用します。出力はバイト単位になり、必要に応じて解析およびフォーマットできます。

$ 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

しかし、zfsの人間が判読可能な出力を解析して「正確な」数値に変換することはできません。人間が判読可能な数値は (たとえば) 3 桁の有効数字のみに指定されているため、「正確な」外挿も 3 桁までしか正確ではありません。

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

答え2

使用できますnumfmt(Debian とその派生版では、これはその一部なのでcoreutils、すでに存在しているはずです):

numfmt - 数値を人間が読める文字列に変換する

$ numfmt --from=iec-i 50.1Gi
53794465383

stdinから値を読み取ることもできる

$ echo "50.1Gi" | numfmt --from=iec-i
53794465383

小数点記号のロケールを考慮するので注意してください。

答え3

zpool list数値をバイト単位で提供できます。たとえば、メインの zfs サーバー上の 3 つのプール (15T、29T、416G) を一覧表示します。

まず、-Hとがない場合-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%

そしてまた、-Hそして-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

出力はタブで区切られているので、awkまたはcutまたは好きな方法で簡単に処理できます(シェルのwhile readループでもかまいません)。主張する)。このcapacityフィールドは使用率を表すため、プールの空き容量が 10% または 20% を下回った場合にアラートを電子メールで送信する場合に特に便利です。

  • -HScripted mode. Do not display headers, and separate fields by a single tab instead of arbitrary space.
  • -p「人間が読める」形式(つまりバイト)ではなく、「解析可能な」形式を出力します。

ちなみに、最近のバージョンの ZFS では、zfsおよびのマニュアル ページがサブコマンド、プロパティ、概念などごとに別々のページに分割されています。これを実行している場合は、詳細については、zpoolおよびのマニュアル ページを参照してください。それ以外の場合は、 だけです。zpool-listzpoolpropsman zpool

答え4

タグと文言が付いているので、bash楽しみのためにこれを投稿します。

検証なし。(ユニットが存在するかどうかなど)

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

IEC 基本量 1024 (2^10) (小数点 2 桁を使用)

最大 81.914P (64 ビット) (小数点 3 桁を使用する場合は 8.191 など)

#!/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

関連情報