如何将tar压缩操作通过管道传输到AWS s3 cp?

时间:2019-07-17 15:14:35

标签: bash amazon-s3 pipe aws-sdk tar

我正在用bash编写自定义备份脚本供个人使用。目标是通过tar / gzip压缩目录的内容,分割压缩的存档,然后将这些部分上传到AWS S3。

几个月前,我第一次尝试编写此脚本时,就可以通过以下方式使其工作:

tar -czf - /mnt/STORAGE_0/dir_to_backup | split -b 100M -d -a 4 - /mnt/SCRATCH/backup.tgz.part
aws s3 sync /mnt/SCRATCH/ s3://backups/ --delete
rm /mnt/SCRATCH/*

这对我来说很好用,但是需要/mnt/SCRATCH有足够的磁盘空间来存储压缩目录。现在,我想改进此脚本,以不必依赖/mnt/SCRATCH中有足够的空间,并进行了一些研究。我最终得到了这样的东西:

tar -czf - /mnt/STORAGE_0/dir_to_backup | split -b 100M -d -a 4 --filter "aws s3 cp - s3://backups/backup.tgz.part" -

这几乎可行,但是我的S3存储桶上的目标文件名不是动态的,并且似乎在运行时会多次覆盖backup.tgz.part文件。最终结果只是一个100MB的文件,而预期的几个100MB的文件以.part0001结尾。

任何指导将不胜感激。谢谢!

2 个答案:

答案 0 :(得分:1)

使用split时,可以使用env变量$FILE来获取生成的文件名。 参见split man page

--filter=COMMAND
     write to shell COMMAND; file name is $FILE

对于您的用例,您可以使用类似以下的内容:

--filter 'aws s3 cp - s3://backups/backup.tgz.part$FILE'

(需要单引号,否则环境变量替换将立即发生)

这将在aws上生成以下文件名:

backup.tgz.partx0000
backup.tgz.partx0001
backup.tgz.partx0002
...

完整示例:

tar -czf - /mnt/STORAGE_0/dir_to_backup | split -b 100M -d -a 4 --filter 'aws s3 cp - s3://backups/backup.tgz.part$FILE' -

答案 1 :(得分:1)

您应该能够使用 GNU Parallel 相当轻松地并行完成它。它具有--pipe选项,可将输入数据分割成大小为--block的块,并将其分配到多个并行进程中。

因此,如果您要使用100MB块并并行使用CPU的所有内核,并将块号({#})附加到AWS上文件名的末尾,则命令应如下所示:

tar czf - something | parallel --pipe --block 100M --recend '' aws s3 cp - s3://backups/backup.tgz.part{#}

您只能使用4个CPU内核,而不能使用parallel -j4的所有内核。

请注意,我将“记录末尾” 字符设置为空,以便它不会尝试避免分割中线,这是它的默认行为,比二进制文件更适合于文本文件处理像tarball。