使用 bpipe 插件与 Bareos Backup 时出现错误:
致命错误:bpipe-fd:管道读取错误:ERR=Error 0
后
zfs send -R dpool/some_dataset
已完成,从 bash 脚本执行。
但只有当且仅当 dpool/some_dataset 有子数据集时(例如有 dpool/some_dataset/child1)。-R 选项在 zfs 发送中包含子数据集。这是我的脚本zfs_create_send_snapshot.sh:
#!/bin/sh
#
# create recursive ZFS snapshot for given dataset and pipe
# replication stream to stdout, then delete snapshot
if [ -z "$1" ]; then
(>&2 echo "ERROR: missing dataset name argument")
exit 1
fi
DDD=`date +%y%m%d%H%M`
SNAPNAME=$1@bareos_${DDD}
(>&2 echo "creating ZFS snapshot ${SNAPNAME}")
zfs snapshot -r ${SNAPNAME}
(>&2 echo "sending ZFS snapshot ${SNAPNAME}")
zfs send -R ${SNAPNAME}
RC=$?
(>&2 echo "deleting ZFS snapshot ${SNAPNAME}")
(>&2 zfs destroy -r ${SNAPNAME})
exit ${RC}
它由 bareos 文件集执行,如下所示:
Plugin = "bpipe:file=/tmp/zfs_snap.bin:reader=/etc/bareos zfs_create_send_snapshot.sh dpool/some_dataset:writer=/etc/bareos/writer.sh /tmp/zfs_snap.bin"
仅当 dpool/some_dataset 具有子 zfs 数据集时,作业才会因管道损坏错误而失败。否则一切都很好。而且这似乎只是一个副作用:备份作业将完整的 zfs 快照流写入磁带,直到——只是错误地因错误而完成。它发生在 openindiana/illumos 上。最近的 Bareos 客户端 17.2 从 git 源编译而来。
答案1
显然,我通过搜索找到了解决问题的方法如何在 bash 中回显 EOF?
由于某些不为人知的原因zfs_create_send_snapshot.sh脚本终止它的标准输出的方式有所不同,这取决于zfs 发送确实发送了多个文件系统...非常奇怪。
因此,在脚本中添加exec 1>&-
后缀zfs send
即可解决问题。
#!/bin/sh
#
# create recursive ZFS snapshot for given dataset and pipe
# replication stream to stdout, then delete snapshot
if [ -z "$1" ]; then
(>&2 echo "ERROR: missing dataset name argument")
exit 1
fi
DDD=`date +%y%m%d%H%M`
SNAPNAME=$1@bareos_${DDD}
(>&2 echo "creating ZFS snapshot ${SNAPNAME}")
zfs snapshot -r ${SNAPNAME}
(>&2 echo "sending ZFS snapshot ${SNAPNAME}")
zfs send -R ${SNAPNAME}
RC=$?
exec 1>&-
(>&2 echo "deleting ZFS snapshot ${SNAPNAME}")
(>&2 zfs destroy -r ${SNAPNAME})
exit ${RC}
顺便说一句:有人可以指出这个奇怪的exec 1 >&-
语法/命令的参考吗?
深入挖掘根本原因,我在 bareos fd 源 (bareos/core/src/plugins/filed/bpipe-fd.cc) 中发现了以下代码片段:
case IO_READ:
if (!p_ctx->pfd) {
Jmsg(ctx, M_FATAL, "bpipe-fd: Logic error: NULL read FD\n");
Dmsg(ctx, debuglevel, "bpipe-fd: Logic error: NULL read FD\n");
return bRC_Error;
}
io->status = fread(io->buf, 1, io->count, p_ctx->pfd->rfd);
if (io->status == 0 && ferror(p_ctx->pfd->rfd)) {
io->io_errno = errno;
Jmsg(ctx, M_FATAL, "bpipe-fd: Pipe read error: ERR=%s\n",
strerror(io->io_errno));
Dmsg(ctx, debuglevel, "bpipe-fd: Pipe read error: ERR=%s\n",
strerror(io->io_errno));
return bRC_Error;
}
break;
也许缺少 feof()?只是猜测……