作为备份系统的一部分,我们将 zfs 数据集从 TrueNAS 系统复制到几个备份服务器,其中一个运行 TrueNAS Scale 并连接了 LTO-5 磁带驱动器。我们偶尔会将其中一个只读快照的内容写入磁带。由于其中一些数据集很大,因此使用 tar 和 --multi-volume 标志。
备份之前,会为快照目录中的每个文件生成 sha256sum。此文件的副本保存在服务器上,并写入磁带。
此后,快照的全部内容将使用
tar --acls --xattrs --spares --label="SomeLabel" --multi-volume -cvpf /dev/nst0 *
这对我们很有帮助,但是,我希望在将数据写入磁带后对其进行验证。我想避免需要将整个文件数据集提取到临时位置,否则将允许运行“sha256sum -c”,因为 TrueNAS 秤服务器没有足够的额外空间来提取某些数据集。相反,我尝试了:-
tar --multi-volume -xf /dev/nst0 --to-command=tar-shasums.sh | tee verify-datasetname.sha25sum
tar-shasums.sh 的内容如下:
#!/bin/bash
sha1=`sha1sum`
echo -n $sha1 | sed 's/ .*$//'
echo " $TAR_FILENAME"
但是,如果 tar 跨越两盘磁带,我就会遇到一个问题。当 tar 正在读取跨越两盘磁带的文件时,它会要求插入下一卷并按下回车键。但是,这会出错,因为设备正在使用中。
看起来“--to-command”对该文件仍然有效,因为它尚未接收到生成 shasum 的所有数据,但它在磁带更换之前也无法完成,但磁带在完成之前无法更换......
目前我终止了 shasum 进程,这允许 tar 继续处理下一盘磁带,但这意味着无法验证跨越两个卷的一个文件。除非手动提取和检查该文件。不太理想。
我以为答案是否定的,但是,有什么办法可以解决这个问题吗?有没有办法生成 shasum,而不需要先将整个 tar 提取到磁盘?或者,有没有办法打破 /dev/nst0 上的锁定,让 tar 继续从新插入的磁带读取,而不必终止 shas256sum?
答案1
我昨晚查看了 tar 源代码,看起来“--to-command”确实创建了一个管道,然后它使用 fork 来运行脚本并将文件数据通过管道传输给它。
因此,问题是,fork 导致分叉进程继承所有父文件描述符,其中包括 tar 已打开的 /dev/nst0 设备。然后 Tar 关闭 /dev/nst0 以准备进行媒体更改,但等待更多管道数据的分叉进程仍将其打开,因此出现死锁。
我通过更改其运行的脚本来部分解决此问题,使其始终关闭 /dev/nst0 描述符
DEVICE=/dev/nst0
file=`lsof -p $$ | grep ${DEVICE} | awk '{print $4}'`
file=${file::-1}
eval "exec ${file}<&-"
然后只有一个进程“sh”似乎仍然挂在文件描述符上。 “fuser -u /dev/nst0”显示了这一点,作为临时解决方法,可以使用 gdb 将其关闭,之后媒体更改和其余校验和即可正确生成。
gdb -p PID
p close(FD)
我不确定是否可以使用 fork 但不将所有文件描述符传递给分叉进程,但这看起来是最终的解决方案。
如果我明白了,我会更新这个答案。