我正在尝试验证我的 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 能够在备份运行过程中修复丢失的哈希值,只要文件的正确版本仍然存在,那么这将是一个改进。
所以我最终复制了“损坏”的备份并制作了一个新的。即使没有哈希值,“损坏”的备份仍可用于恢复,但它会生成大量警告。因为我每晚都会进行恢复,所以我不想收到有关丢失哈希值的警告。我还怀疑,如果没有哈希值,恢复速度会更慢,但我没有验证这一点。