Skip to content

Instantly share code, notes, and snippets.

@n-st
Last active April 29, 2017 14:35
Show Gist options
  • Save n-st/890dc45be2adf6b12c80 to your computer and use it in GitHub Desktop.
Save n-st/890dc45be2adf6b12c80 to your computer and use it in GitHub Desktop.
Quick'n'dirty script to display the progress and ETA of a running btrfs scrub
#!/bin/zsh
# usage: $0 <path being scrubbed>
set -e
# adapted from my own oneliner script at http://www.commandlinefu.com/commands/view/12621/
format_filesize () {
printf "%d" $1 | awk 'function hr(bytes){hum[1024**4]="TiB";hum[1024**3]="GiB";hum[1024**2]="MiB";hum[1024]="kiB";for(x=1024**4;x>=1024;x/=1024){if(bytes>=x){return sprintf("%8.3f %s",bytes/x,hum[x]);}}return sprintf("%4d B",bytes);}{print hr($1) "\t" $2}'
}
format_time () {
printf "%d min %d s" $(($1/60)) $(($1 % 60))
}
btrpath="$1"
used=$(($(btrfs fi df $btrpath | sed 's/^.\+ single:/:/gi;s/^.\+ DUP:/2*:/gi;s/: .*used=//g;s/GiB$/*1024*1024*1024/g;s/MiB$/*1024*1024/g;s/KiB$/*1024/g;s/$/+/g;$s/\+//g' | xargs)))
seconds=$(btrfs scrub status $btrpath | grep -oP '(?<=running for )[[:digit:]]+(?= seconds)')
scrubbed=$(($(btrfs scrub status $btrpath | grep -oP '(?<=total bytes scrubbed: )[0-9.GMKiB]+(?= with)' | sed 's/GiB$/*1024*1024*1024/g;s/MiB$/*1024*1024/g;s/KiB$/*1024/g')))
percent=$((100.0*$scrubbed/$used))
totaltime=$(($seconds/($percent/100.0)))
eta=$(($totaltime - $seconds))
printf "scrubbed %s of %s (%.2f%%)\n%s remaining (of %s total)\n" "$(format_filesize $scrubbed)" "$(format_filesize $used)" $percent "$(format_time $eta)" "$(format_time $totaltime)"
@racmar
Copy link

racmar commented Apr 29, 2017

The above did not work with my TiB sized btrfs filesystem. I modified the file to work for me, here are my changes if you are interested.

#!/bin/zsh

# usage: $0 <path being scrubbed>

set -e

# adapted from my own oneliner script at http://www.commandlinefu.com/commands/view/12621/
format_filesize () {
    printf "%d" $1 | \
    awk '\
      function hr(bytes)\
      {hum[1024**4]="TiB";hum[1024**3]="GiB";hum[1024**2]="MiB";hum[1024]="kiB";\
      for(x=1024**4;x>=1024;x/=1024)\
      {if(bytes>=x){return sprintf("%.2f %s",bytes/x,hum[x]);}}\
      return sprintf("%4dB",bytes);}{print hr($1) $2}\
    '
}
format_time () {
    secs=$1
    printf '%dh:%dm:%ds\n' $(($secs/3600)) $(($secs%3600/60)) $(($secs%60))
}
human_to_bytes () {
  printf $1 | sed 's/TiB$/*1024*1024*1024*1024/g;s/GiB$/*1024*1024*1024/g;s/MiB$/*1024*1024/g;s/KiB$/*1024/g'
}

btrpath="$1"
btrfs_usage=$(btrfs fi usage $btrpath)
btrfs_scrub_status=$(btrfs scrub status $btrpath)
used=$(($(human_to_bytes $(grep -oP '(?<=Used:)\s*?[0-9.TGMKiB]+' <<< "$btrfs_usage" | head -1 | awk '{print ($1)}'))))
if [[ $btrfs_scrub_status == *" finished after "* ]]; then
  seconds=$(($(grep -oP '(?<=finished after ).*' <<< "$btrfs_scrub_status" | awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }')))
else
  seconds=$(($(grep -oP '(?<=running for ).*' <<< "$btrfs_scrub_status" | awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }')))
fi
scrubbed=$(($(human_to_bytes $(grep -oP '(?<=total bytes scrubbed: )[0-9.TGMKiB]+(?= with)' <<< "$btrfs_scrub_status"))))
percent=$((100.0*$scrubbed/$used))
totaltime=$(($seconds/($percent/100.0)))
eta=$(($totaltime - $seconds))

printf "scrubbed (%s) of (%s) at (%.2f%%) complete," "$(format_filesize $scrubbed)" "$(format_filesize $used)" $percent
printf " average speed (%s/s)," "$(format_filesize $(($scrubbed/$seconds)))"
printf " %s elapsed, %s total, (%s remaining)\n" "$(format_time $seconds)" "$(format_time $totaltime)" "$(format_time $eta)"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment