拆分 tar 档案并一次上传一个

拆分 tar 档案并一次上传一个

我想使用脚本逐个上传系统,将系统备份到拆分的 tar 存档中。它必须创建拆分存档,然后运行脚本。脚本上传部分并删除它。这是为了确保备份不会占用系统上的太多空间。我可以创建拆分存档并上传它们,但我需要 50% 的可用空间。所以我需要一次创建一个。我在寻求有关最佳方法的建议。我有几个想法,你可以建议一个更好的。

方法一:使用 tar 本身拆分档案,并使用 --new-volume-script。这样做的问题是我必须计算备份的大小。Tar 似乎需要具体说明将存在多少部分以及它们必须有多大。这意味着我的脚本必须计算这一点并生成 tar 的参数。

tar -c -M -L 102400 --file=disk1.tar --file=disk2.tar --file=disk3.tar largefile.tgz

这将为每个部分创建三个 100Mb 的文件。如果有一种方法可以动态地执行此操作,使用 tar 自动命名文件并创建所需的文件数量,我想知道,因为这将使这种方法可行。

方法二:编写自己的脚本,使其行为类似于 split。tar 的输出在 stdin 上提供给它,它会上传文件并让 tar 等待。这将是最简单的解决方案。

答案1

该解决方案不使用tar,但您可以使其与afio.拆分存档的所有逻辑一起工作,这些逻辑都是内置的,并且可以选择在每次卷拆分后运行脚本:

cd /path/to/files -print | \
   afio -oxv -s 1g -H rotate.sh backup-`date -Imin`-Vol%V.afio

rotate.sh是上传和删除每个存档文件的脚本。这将生成存档:

backup-2014-11-29T18:04-0500-Vol1.afio
backup-2014-11-29T18:04-0500-Vol2.afio
backup-2014-11-29T18:04-0500-Vol3.afio
...

rotate.sh并在每卷完成后运行。

其他选择:

-o              # create an archive
-x              # perserve ownership suid/sgid
-v              # verbose
-s 1g           # split archives after 1g
-H rotate.sh    # run this script after each 'tape change'
-Z -P xz        # Compress, and use xz instead of gzip
 # Also, %V, below, inserts the volume number into the file name
 backup-`date -Imin`-Vol%V.afio               

其他afio方面:它与类似,cpio,只是它专门针对脚本备份。此外对于压缩档案来说更安全因为它会单独压缩每个文件,而不是压缩整个文件流。这样,压缩后的数据损坏只会影响一个文件,而不是整个存档。同样,它还可以在存储每个文件时对其进行 gpg 加密,这对于云存储非常有用。

答案2

此答案最初发布于https://unix.stackexchange.com/a/752289/320221

我没有真正的 SSH 访问权限,因为它是一个托管主机。我正在使用https://github.com/flozz/p0wny-shell有类似贝壳的东西。

我找到的该问题的初步答案是:https://unix.stackexchange.com/a/628242/320221
它创建了各个部分并暂停read。问题是,p0wny-shell 不提供 stdin 流,因此该read命令不会停止脚本,并且各个部分仍然会一个接一个地创建,而不会暂停。

我做了修改,以便它自动将各个部分逐一移动到新服务器:

  1. 创建零件
  2. 上传该部分并删除它
  3. 重复此操作,直到创建所有部件
  4. 手动上传最后一部分
  5. 使用原始 myscript.sh 在远程服务器上解压它(没有read各部分之间的 to not stop)
#!/bin/bash
# For this script it's advisable to use a shell, such as Bash,
# that supports a TAR_FD value greater than 9.

if [[ $TAR_SUBCOMMAND != '-c' ]]; then
  echo 'This script can only be used to compress with -c option'
  exit 1;
fi

# $TAR_ARCHIVE per run:
# 1. archive.tar
# 2. archive.tar-2
# 3. archive.tar-3
# ...

# $TAR_ARCHIVE_NAME per run
# 1. <empty>
# 2. archive.tar
# 3. archive.tar
# ...
TAR_ARCHIVE_NAME=`expr $TAR_ARCHIVE : '\(.*\)-.*'`

# $TAR_ARCHIVE_BASE_NAME per run
# 1. archive.tar
# 2. archive.tar
# 3. archive.tar
# ...
TAR_ARCHIVE_BASE_NAME=${TAR_ARCHIVE_NAME:-$TAR_ARCHIVE}

if (( $TAR_VOLUME == 2 )); then
  # On the first run $TAR_VOLUME will be '2', we want to use the base name
  TAR_ARCHIVE_PREV_PART=$TAR_ARCHIVE_BASE_NAME
elif (( $TAR_VOLUME >= 3 )); then
  # On the next runs $TAR_VOLUME we want to build the name with the previous $TAR_VOLUME
  TAR_PREV_VOLUME=$(($TAR_VOLUME-1))
  TAR_ARCHIVE_PREV_PART=$TAR_ARCHIVE_BASE_NAME-$TAR_PREV_VOLUME
fi


echo "Copying $TAR_ARCHIVE_PREV_PART..."
# SSH key was previously created with `ssh-keygen -f ./id_rsa_user` and public key was added to remote
scp \
  -o StrictHostKeyChecking=no \
  -i '/usr/www/users/user/.ssh/id_rsa_user' \
  $TAR_ARCHIVE_PREV_PART \
  [email protected]:/home/user/path/to/target/


echo "Removing $TAR_ARCHIVE_PREV_PART..."
rm $TAR_ARCHIVE_PREV_PART


echo Preparing volume $TAR_VOLUME of $TAR_ARCHIVE_BASE_NAME.
echo $TAR_ARCHIVE_BASE_NAME-$TAR_VOLUME >&$TAR_FD

相关内容