微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

连接 tar 文件,以便可以在没有 -i 选项的情况下打开生成的 tar

如何解决连接 tar 文件,以便可以在没有 -i 选项的情况下打开生成的 tar

我得到了包含许多非常小的 JSON 文件的 tar 档案。每天我都会得到一个新的 tar 档案。现在我想将每日 tar 档案合并为一个年度 tar 档案并进行压缩。我使用以下 bash 脚本执行此操作:

tar -cf "/mnt/archive/archive - 2020.tar" --files-from /dev/null
for f in /mnt/data/logs/2020/logs-main-2020-??-??.tar
do
    tar -n --concatenate --file="/mnt/archive/archive - 2020.tar" $f
done

pxz -T6 -c "/mnt/archive/archive - 2020.tar" > "/mnt/archive/archive - 2020.tar.xz"
rm "/mnt/archive/archive - 2020.tar"

这是可行的,但是主 tar 越大,tar 文件的连接越慢。

我可以使用 cat 指令简单地将所有 tar 加在一起,但生成的存档然后包含原始 tar 的所有存档结束空标记。因此,必须使用 -i 选项打开生成的 tar,这不是使用生成的 tar 的系统的选项。

如何在不需要慢速 tar 连接的情况下连接 tar 文件,并且仍然创建一个有效的 tar 中间没有空值?我可以做一些 cat、un-tar、re-tar、压缩管道吗?

  • 我在输入 tars 的 JSON 文件名中没有任何空格字符,例如换行符
  • 我在 CentOS 7 上使用 GNU tar v1.26
  • 每个输入 tar 大约为 1GB,因此无法将它们保存在内存中
  • 无需检查输出 tar 中的重复条目。输入 tar 的创建方式确保它们没有重复的 JSON 文件

解决方法

几种基于 perl 的方法:

首先,脚本使用核心 Archive::Tar 模块读取现有的 tar 文件并创建一个新的文件(由于模块的限制,它必须将合并后的目标 tar 文件的数据保存在内存中)在写入之前一次;可能是大量数据的问题):

#!/usr/bin/env perl
use warnings;
use strict;
use feature qw/say/;
use Archive::Tar;

# First argument is the new tar file to create,rest are ones to
# copy files from.

die "Usage: $0 DESTFILE SOURCEFILE ...\n" unless @ARGV >= 2;

my $destfile = shift;
my $dest = Archive::Tar->new;

foreach my $file (@ARGV) {
  my $src = Archive::Tar->iter($file) or exit 1;
  say "Adding contents of $file";
  while (my $file = $src->() ) {
    my $name = $file->full_path;
    say "\t$name";
    $dest->add_data($name,$file->get_content,{ mtime => $file->mtime,size => $file->size,mode => $file->mode,uid => $file->uid,gid => $file->gid,type => $file->type,devmajor => $file->devmajor,devminor => $file->devminor,linkname => $file->linkname
                    })
      or exit 1;
  }
}

$dest->write($destfile) or exit 1;
say "Wrote $destfile";

用法:

perl tarcat.pl "/mnt/archive/archive - 2020.tar" /mnt/data/logs/2020/logs-main-2020-??-??.tar

或者使用 Archive::Tar::Merge 的单行(如果提供的话,通过你的操作系统包管理器安装,或者最喜欢的 CPAN 客户端;不确定它的内存限制):

perl -MArchive::Tar::Merge -e '
    Archive::Tar::Merge->new(dest_tarball => $ARGV[0],source_tarballs => [ @ARGV[1..$#ARGV] ])->merge
' "/mnt/archive/archive - 2020.tar" /mnt/data/logs/2020/logs-main-2020-??-??.tar

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。