Tar管道结合xargs执行出错中断,如何实现续跑忽略错误?
问题根源与解决方案
核心错误分析
你当前的命令存在两个致命问题:
- xargs用法完全错误:
$(tar xvf - --keep-newer-files -C /pathto/destination)是命令替换,shell会先执行这个tar解压命令,将其输出的文件名列表作为xargs的命令参数,这直接导致了xargs: Argument list too long错误——大量文件名超出了shell参数长度限制。同时这个逻辑完全违背了在线复制的流式处理初衷。 - 错误参数的作用范围不对:
--ignore-failed-read仅对打包端的tar c生效,用于跳过打包时无法读取的源文件,但解压端的tar x遇到不完整归档(比如源文件被删导致打包提前终止)时,仍会因EOF报错退出,这个参数无法影响解压端的行为。
解决方案一:修复tar流式复制,添加错误忽略参数
如果不需要并行处理,直接修正命令结构,给解压端的tar添加忽略EOF错误的参数即可:
tar cvf - --sort=name --ignore-failed-read -C /pathto/source . | pv | tar xvf - --keep-newer-files --ignore-zeros -C /pathto/destination
- 移除了错误的xargs部分,恢复tar管道的流式复制逻辑
- 解压端添加
--ignore-zeros参数:让tar忽略归档中的零块(通常由意外EOF导致),继续处理能读取到的内容 - 保留打包端的
--ignore-failed-read:确保打包时遇到无法读取的源文件(如被删除)时跳过,避免打包提前终止导致归档不完整
解决方案二:并行处理小文件,单个错误不中断整体任务
针对你文件数量多、体积小的场景,用文件列表+并行复制的方式更合适,单个文件复制失败不会中断整个任务:
用xargs实现:
tar cf - --sort=name --ignore-failed-read -C /pathto/source . | tar tf - | xargs -I {} -P 32 sh -c ' src="/pathto/source/{}" dst="/pathto/destination/{}" # 确保目标目录存在 mkdir -p "$(dirname "$dst")" # 复制文件,保留属性,跳过已更新的文件 cp -a --no-preserve=links --update "$src" "$dst" || echo "复制失败: $src" >> copy_errors.log '
用parallel实现(更简洁高效):
tar cf - --sort=name --ignore-failed-read -C /pathto/source . | tar tf - | parallel -j 32 ' src="/pathto/source/{}" dst="/pathto/destination/{}" mkdir -p "$(dirname "$dst")" cp -a --no-preserve=links --update "$src" "$dst" || echo "复制失败: $src" >> copy_errors.log '
- 先用
tar tf -解析归档,获取源文件的相对路径列表 - 并行调用
cp复制单个文件,--update对应原命令的--keep-newer-files,仅复制比目标新的文件 - 添加错误日志输出,方便后续批量处理失败的文件
内容的提问来源于stack exchange,提问作者t.mas
相关产品推荐
相关产品推荐

