Parchive

出自 ArchWiki

Parchive (奇偶校验档案) 是一款文件验证和修复工具,它使用 PAR2 文件来检测数据文件中的损坏,并在必要时修复它们。它可以用于任何类型的文件。

安装

安装 par2cmdline 软件包。命令 par2par2createpar2verifypar2repair 现在可用。

工作原理

par2create 接受输入文件,并将输入解释为一定数量的数据块。基于数据块,par2create 随后借助 w:里德-所罗门纠错 码创建恢复块。稍后,您可以将任何恢复块换取任何损坏的数据块,以便修复源数据。您需要与损坏的数据块一样多的恢复块,才能成功修复文件。

假设您想为一个珍贵的文件计算 30% 的恢复信息

$ par2create -r30 file

Parchive 现在创建了 file.par2 索引文件,该文件对于恢复而言本质上是不需要的。此外,它还创建了恢复块,并将它们分散到多个文件中。如果您创建了,例如,592 个恢复块,您将找到文件

file.vol000+001.par2
file.vol001+002.par2
file.vol003+004.par2
file.vol007+008.par2
file.vol015+016.par2
file.vol031+032.par2
file.vol063+064.par2
file.vol127+128.par2
file.vol255+256.par2
file.vol511+081.par2

加号左边的数字是特定文件中第一个恢复块的索引,右边的数字是该文件提供的恢复块的数量。

在早期,链路层上没有完整性检查,这些文件被证明是有用的,因为人们可以根据损坏的数据块的数量来选择恢复文件。如果您的下载留下 43 个损坏的数据块,您可以将该数字转换为二进制,并立即查看您必须获取哪些恢复文件

    32 16  8  4  2  1
43 = 1  0  1  0  1  1

→ download *+032.par2, *+008.par2, *+002.par2 and *+001.par2.

这在带宽使用方面非常有效。最终会调用

$ par2repair file*.par2

以修复下载的文件。您可以忽略索引文件,因为 Parchive 可以处理丢失的索引文件。有时,包含 -N 参数很有用,以便找到原本会被检测不到的完整数据块。

技巧与诀窍

批量保护您的文件

可能您不想为客户端提供恢复文件,但希望确保文件的额外完整性。在充氦硬盘驱动器、叠瓦式磁记录技术、每平方厘米高密度容量、传输丢失等时代,位衰减的概率很高。请记住,您应该始终拥有(自动化的)数据备份,但一点额外的保护并没有坏处,尤其是在我们今天拥有如此多的可用存储空间的情况下。通过创建 par2 文件,您可以比运行应用程序程序遍历文件并筛选错误输出,更方便地验证数据的完整性并恢复数据。现在位衰减可能发生在原始文件和恢复文件中,但您仍然可以修复原始文件。

因此,包含所有恢复包的一个恢复文件就足够了(参数 -n1)。这也减少了恢复数据量。一个需要回答的重要问题是您想要拥有的冗余百分比。特别是对于较小的文件(<1 MiB),恢复数据量与原始文件大小并不真正相关

原始数据 百分比 恢复数据(不含索引)
184.8 KiB 5 287.8 KiB
184.8 KiB 100 743.1 KiB
3.4 MiB 5 458.8 KiB
3.4 MiB 30 1.5 MiB
3.4 MiB 100 4 MiB
1.7 GiB 5 87.6 MiB

5% 是合理的恢复数据量,但对于真正重要的文件,您可以高达 100% 的恢复数据。如果您不小心删除了原始文件,并且懒得在备份中搜索该文件(您有备份,对吧? :)),100% 的恢复文件可以恢复您的文件。

这是一个简单的脚本,它递归地遍历当前目录并批量保护文件

提示: 您可能需要确保您的 bin/ 文件夹在搜索路径中
$ export PATH=$PATH:$HOME/bin/
将此行放入您主目录的 init 文件中以使其永久生效。
~/bin/batchprotect.sh
#!/bin/bash
readonly REDUNDENCY_PERCENTAGE=5
readonly PRINT_ON_SUCCESS=1

create_par2() {

  local current_file="${1}"
  if [ ! -e "${current_file}-5p.par2" ] && [ -s "${current_file}" ]; then
    if par2create -n1 -q -q -r"${REDUNDENCY_PERCENTAGE}" "${current_file}"; then

      if [ "${PRINT_ON_SUCCESS}" = 1 ]; then
        printf '\033[1;37m%s \033[1;34m%s \033[1;32m%s \033[0m\n' \
                'Creating par2 on' "${current_file}" 'successful'
      fi

      rm "${current_file}.par2"
      mv "${current_file}".vol*par2 "${current_file}-${REDUNDENCY_PERCENTAGE}p.par2"
      return 0

    else
      printf '\033[1;37m%s \033[1;34m%s \033[1;31m%s \033[0m\n' \
              'Creating par2 on' "${current_file}" 'failed'
      return 1
    fi
  fi
}

verify_par2() {

  local current_file="${1}"
  if [ -f "${current_file}-${REDUNDENCY_PERCENTAGE}p.par2" ]; then
    if par2verify -q -q "${current_file}-${REDUNDENCY_PERCENTAGE}p.par2"; then
      if [ "${PRINT_ON_SUCCESS}" = 1 ]; then
        printf '\033[1;37m%s \033[1;34m%s \033[1;32m%s \033[0m\n' \
                'Verifying par2 on' "${current_file}" 'successful'
      fi
      return 0
    else
      printf '\033[1;37m%s \033[1;34m%s \033[1;31m%s \033[0m\n' \
              'Verifying par2 on' "${current_file}" 'failed'
      return 1
    fi
  fi
}

repair_par2() {

  local current_file="${1}"
  if [ -f "${current_file}-${REDUNDENCY_PERCENTAGE}p.par2" ]; then
    if par2repair -p -q -q "${current_file}-${REDUNDENCY_PERCENTAGE}p.par2"; then
      if [ "${PRINT_ON_SUCCESS}" = 1 ]; then
        printf '\033[1;37m%s \033[1;34m%s \033[1;32m%s \033[0m\n' \
                'Repairing' "${current_file}" 'successful'
      fi
      return 0
    else
      printf '\033[1;37m%s \033[1;34m%s \033[1;31m%s \033[0m\n' \
              'Repairing' "${current_file}" 'failed'
      return 1
    fi
  fi
}

main() {

  while read -r current_file; do
    # Create or verify
    if [ ! -e "${current_file}-${REDUNDENCY_PERCENTAGE}p.par2" ]; then
      create_par2 "$current_file"
    else
      if ! verify_par2 "$current_file"; then
        repair_par2 "$current_file"
      fi
    fi
  # We ignore the file itself, any par2/sig extension and any .git directory and print without the leading ./
  done < <(find . -type f ! -name '*par2loop.sh' ! -name '*par2' ! -name '*.sig' ! -path '*.git*' -prune -a -printf '%P\n' | shuf)
}

main

然后您将调用 batchprotect.sh,以便让当前目录中的所有文件(递归地)都受到 Parchive 的保护。此外,您不必维护校验和列表,因为 gpg 也可以为您做到这一点。

验证

$ par2verify file-5.par2
$ cfv file-5.par2
$ gpg --verify file.sig

并且,如果您更改了原始文件的路径

$ par2verify -B / file-5.par2 /new/path/to/fileRenamed
$ gpg --verify file.sig /new/path/to/fileRenamed

您也可以更改 par2/sig 文件的路径。