rdiff-backup 警告:元数据文件没有文件摘要

rdiff-backup 警告:元数据文件没有文件摘要

我正在尝试验证我的 rdiff-backup,但似乎一半的文件缺少元数据哈希。这意味着我在运行该--compare-hash函数时会遇到大量错误:

Warning: Metadata file has no digest for Distros/Linux/linuxmint-17.3-cinnamon-64bit.iso, unable to compare.

同样该--verify函数也会产生大量错误:

Warning: Cannot find SHA1 digest for file linuxmint-19.1-cinnamon-64bit.iso,
perhaps because this feature was added in v1.1.1

我的 rdiff-backup 版本是 2.05,所以我不明白为什么它缺少所有这些 SHA1 哈希值。有没有办法重新生成这些哈希值而不用重新进行整个备份?

答案1

我在网上搜索了所有出现相同错误的帖子,抱怨缺少 SHA1 和,但似乎没有人有任何解决方案。因此,我决定手动查看元数据文件并编写一个脚本来简单地“填写”缺少 SHA1 和的条目。

您可以通过键入以下内容来运行脚本fix_metadata.py <your backup directory>- 原始元数据文件已备份,但到目前为止,在我的测试中,这似乎解决了问题。我仍然想知道为什么这么多文件一开始就缺少校验和。

#!/usr/bin/python3
# Usage: fix_metadata.py <backup folder>

import re, gzip, hashlib, os, time, sys

def digest(filename, chunk=1024**2):
    #Compute sha1 digest
    h = hashlib.sha1()
    print("Calculating hash of:", filename, end='')
    count = 0
    with open(filename, 'rb') as f:
        while True:
            data = f.read(chunk)
            if data:
                h.update(data)
                count += 1
                if not count % 100:
                    print('.', end='', flush=True)
            else:
                print()
                return h.hexdigest()


os.chdir(sys.argv[1])
for meta in os.listdir('rdiff-backup-data'):
    if 'metadata' in meta and meta.endswith('.gz'):
        meta = os.path.join('rdiff-backup-data', meta)
        fixed = meta+'.fixed'
        print("Processing:", meta)
        output = gzip.open(fixed, 'w')
    else:
        continue
    
    entry = []      #Entry for a single file
    sha1 = False    #Did we find a SHA1 hash?
    updated = 0     #Number of entries updated
    with gzip.open(meta, 'rt') as f:
        for line in f:
            if line.startswith('File '):
                if entry and not sha1:
                    filename = (re.sub('^File','', entry[0])).strip()
                    if os.path.exists(filename):
                        if os.path.isfile(filename):
                            entry.insert(3, '  SHA1Digest ' + digest(filename.strip())+'\n')
                            updated += 1
                    else:
                        print("Could not find file:", filename)
                output.write(''.join(entry).encode())
                entry = []      
                sha1 = False
            if line.startswith('  SHA1Digest'):
                sha1 = True
            entry.append(line)
        if entry:
            output.write(''.join(entry).encode())
        output.close()
    if updated:
        print(updated, "files fixed")
        os.rename(meta, meta + '.'+str(int(time.time())) + '.original.bak')
        os.rename(fixed, meta)
        print('Finished:', meta)
    else:
        os.remove(fixed)

答案2

我遇到了同样的问题并尝试使用你的脚本修复它。

因为我的备份有 200GB,并且每天备份两次,所以有很多元文件需要更新。因为这需要很长时间,所以我可以考虑一下这个脚本。它肯定会为所有缺失的文件创建哈希值。但它总是创建文件当前版本的哈希值。所以我更新了文件,在为其创建哈希值之前比较 modTime。但是对于那些没有哈希值且 modTime 不匹配的文件,我该怎么办呢?我没有解决方案。

该脚本可能修复了症状但不能解决问题,并且还为旧版本的文件提供了当前文件的哈希值。

因为哈希值会通过元文件传播,所以如果它们丢失了,也可以使用如下语句检查哈希值何时消失:

zgrep -c  SHA1Digest BACKUP_DIR/rdiff-backup-data/*meta*snapshot.gz

当计数下降时,哈希值就会丢失。我没有找到哈希值消失的原因,但这可能与备份运行失败有关。对于为更改的文件生成错误哈希值的问题,一种解决方法是将哈希值从旧元文件传播到新元文件,只要 modTime 保持不变。希望文件更改/新 modTime 会在新元文件中产生新哈希值。

如果 rdiff-backup 能够在备份运行过程中修复丢失的哈希值,只要文件的正确版本仍然存在,那么这将是一个改进。

所以我最终复制了“损坏”的备份并制作了一个新的。即使没有哈希值,“损坏”的备份仍可用于恢复,但它会生成大量警告。因为我每晚都会进行恢复,所以我不想收到有关丢失哈希值的警告。我还怀疑,如果没有哈希值,恢复速度会更慢,但我没有验证这一点。

相关内容