使用xargs并行tar管道复制大文件系统遇Signal 13错误求助
解决并行tar管道复制超大规模文件系统的SIGPIPE问题
我来帮你搞定这个头疼的并行复制问题。首先得先搞懂你遇到的signal 13是什么——这是SIGPIPE信号,简单说就是你的tar进程往管道里写数据,但管道的另一端已经提前关闭了,系统就会给tar发这个信号终止它。
为什么加-P会报错?
你的原命令是让xargs启动48个tar进程,同时往同一个标准输出管道里写打包数据,然后用一个tar进程在另一端接收解压。这里有两个致命问题:
- 多个tar的打包数据流混在一起,接收端的tar根本无法解析这种混乱的格式,很快就会崩溃退出,导致管道读端关闭;
- 只要有一个tar进程写完数据关闭了写端,剩下还在写的tar进程就会因为管道读端已关闭而收到SIGPIPE,直接被终止。
而去掉-P单线程运行时,只有一个tar写数据,数据流是完整的,所以不会出问题,但速度确实慢得让人抓狂。
可行的解决方案:给每个tar分配独立的管道
我们需要让每个被处理的目录都拥有自己独立的tar cf - | tar xf -管道,避免数据流冲突。用xargs的-I参数就能实现这个需求:
find image -maxdepth 2 -mindepth 2 -type d -print | xargs -P 48 -I {} sh -c 'tar cf - "{}" | (cd /testfiles; tar xf -)'
这个命令的关键细节:
-I {}:把find输出的每个目录路径替换成{},确保每个目录都能被单独处理;sh -c '...':为每个目录启动一个独立的子shell,在子shell里完成单独的打包-解压管道,这样48个并行进程的数据流完全隔离,不会互相干扰;- 给
{}加上双引号:避免目录名包含空格、特殊字符时出现解析错误。
额外优化建议
- 调整并行度:48的并行数不一定是最优的,建议根据你的系统IO能力(比如磁盘带宽、内存)调整,比如先试
-P 16或-P 32,避免IO饱和反而拖慢速度; - 如果有GNU Parallel:可以用它替代xargs,语法更简洁,处理特殊字符也更稳妥:
find image -maxdepth 2 -mindepth 2 -type d -print | parallel -j 48 'tar cf - {} | (cd /testfiles; tar xf -)'
这样修改后,既能利用多核/多IO并行加速,又不会再出现SIGPIPE的错误,处理5000万个文件的效率会提升很多。
内容的提问来源于stack exchange,提问作者frontrange
相关产品推荐
相关产品推荐

