跳转至内容

Parchive

来自 ArchWiki

Parchive(Parity archive)是一个文件验证和修复工具,使用PAR2文件检测数据文件中的损坏并在必要时进行修复。它可以用于任何类型的文件。

安装

安装 par2cmdline 包。现在可以使用 `par2`、`par2create`、`par2verify` 和 `par2repair` 命令。

工作原理

par2create 接收输入文件,并将输入解释为一定数量的数据块。基于数据块,par2create 使用 Reed–Solomon 纠错码创建恢复块。之后,您可以用任何恢复块交换任何损坏的数据块来修复源数据。为了成功修复文件,您需要与损坏的数据块数量相同的恢复块。

假设您想为一份珍贵的文件计算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 参数很有用,以便触及一个否则可能未被检测到的完整数据块。

技巧与提示

批量保护您的文件

您可能不想为客户端提供恢复文件,但又想确保文件的额外完整性。在充斥着氦气的硬盘、叠瓦式磁性记录技术、单位面积高存储密度、传输损耗等技术的时代,比特腐蚀(bit rot)的概率很高。请记住,您应该始终拥有(自动化的)数据备份,但增加一点额外的保护无害,尤其是在我们今天拥有大量存储空间的情况下。通过创建 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 来递归地保护当前目录中的所有文件。此外,您不必维护校验和列表,因为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 文件的路径。

© . This site is unofficial and not affiliated with Arch Linux.

Content is available under GNU Free Documentation License 1.3 or later unless otherwise noted.