Bash脚本,如果速度太慢,则读取rsync进度并对文件进行保释

时间:2018-01-01 00:53:43

标签: bash rsync

我对bash脚本的经验很少,以至于很可笑。

我花了3天时间将文件从我的NAS上的故障硬盘(LVM中的3个中的1个)传输到新硬盘。大多数(百分比)文件传输正常,但许多(数千)受到影响,而不是失败的i / o错误,他们将速度降低到令人痛苦的速度。

我使用的是一个简单的cp命令,但之后我切换到rsync并使用--progress选项至少能够确定何时发生这种情况。

目前,我手动观看屏幕(当我们正在谈论DAYS时很糟糕),^ C出现挂机时,然后复制文件名并将其粘贴到排除文件中并重新启动rsync的。

需要自动执行此操作!

我对bash脚本没有任何了解,但我认为我可以"观看"标准输出,解析费率信息并使用如下逻辑:

if rate is less than 5Mbps for 3 consecutive seconds, bail and restart

这是我使用的rsync命令:     rsync -aP --ignore-existing --exclude-from = EXCLUDE / mnt / olddisk / / mnt / newdisk /

以下是进度的示例输出:

path/to/file.ext
    3434,343,343 54%  144.61MB/s   0:00:05 (xfr#1, ir-chk=1024/1405)

因此解析第二行的第三列并确保它不会太慢,如果它然后终止命令,则将文件名附加到EXCLUDE并再给它一次。

有人可以帮助我吗?

1 个答案:

答案 0 :(得分:2)

This is a horrible approach, and I do not expect it to usefully solve your problem. However, the following is a literal answer to your question.

#!/usr/bin/env bash
[[ $1 ]] || {
  echo "Usage: rsync -P --exclude=exclude-file ... | $0 exclude-file" >&2
  exit 1
}

is_too_slow() {
  local rate=$1
  case $rate in
    *kB/s)          return 0 ;;
    [0-4][.]*MB/s)  return 0 ;;
    *)              return 1 ;;
  esac
}

exclude_file=$1
last_slow_time=0

filename=
too_slow_count=0
while IFS=$'\n' read -r -d $'\r' -a pieces; do
  for piece in "${pieces[@]}"; do
    case $piece in
      "sending incremental file list") continue ;;
      [[:space:]]*)
        read -r size pct rate time <<<"$piece"
        if is_too_slow "$rate"; then
          if (( last_slow_time == SECONDS )); then
            continue # ignore multiple slow results in less than a second
          fi
          last_slow_time=$SECONDS
          if (( ++too_slow_count > 3 )); then
            echo "$filename" >>"$exclude_file"
            exit 1
          fi
        else
          too_slow_count=0
        fi
        ;;
      *) filename=$piece; too_slow_count=0 ;;
    esac
  done
done