ssh 和 tar 进行增量传输(类似 ​​rsync)

ssh 和 tar 进行增量传输(类似 ​​rsync)

在没有 rsync 客户端的托管环境中,我想要执行与 rsync 类似的操作:仅发送已更改的文件。

我将在当前目录上执行此单行命令。这会使用更改的文件更新 archive.tar.gz,然后将文件 scp 到远程站点,最后解压并留下同步目录。我曾设想使用多个管道,但我想我需要一个存档才能真正使用增量功能。

当使用增量时,我对 tar 语法感到困惑。

答案1

同步工具

嗯,如果您只想移动已更改的文件,为什么 tar 命令会更新存档?如果只发送已更改的文件,那么 tar 存档是否只包含这些文件,因此每次都必须从头开始重新创建?

如果我理解正确的话,你想要这样的东西,我称之为bozosync.sh

TarFile=fun.tgz
TheScript=$0
result=
ls -1 . | (
  while read f; do
    if [ -f "$f" -a $f -nt $TheScript ]; then
      result="$result $f"
    fi
  done
  tar cvfz $TarFile $result
  touch $TheScript
)

这会将当前目录中的每个纯文件放入 tar 存档中,对于每个比脚本本身更新的文件,然后它touch(1)在脚本上运行以更新其 mod 时间。这确实存在竞争条件,因为在测试和触摸之间修改的文件将在下一次被忽略。如果这是一个问题,您可以通过在循环之前复制脚本,然后在最后将其移回自身来解决这个问题。(然后你仍然有一个竞争,但失败更温和,它可能只是包含一个没有真正改变的文件。)

答案2

这是修改后的版本数字罗斯的脚本:

#!/bin/bash
TarFile=fun.tgz
TheScript=$0
saveIFS="$IFS"
IFS=$'\n'
files=($( find -maxdepth 1 -type f -newer $TheScript -print ))
tmpfile=$(mktemp)
IFS="$saveIFS"
tar cvfz $TarFile "${files[@]}" && touch -r $tmpfile $TheScript
rm $tmpfile

减少通过将结果保存find在数组中并立即创建临时文件来降低竞争条件的可能性。但这当然不是保证。此外,此脚本避免使用ls。另一个优点是,如果成功,它只会更新脚本的时间戳tar。它还会处理带空格的文件名。

答案3

测试后我做了一些更改,但效果很好,谢谢。

#!/bin/bash
TarFile=transfer-me.tar.gz
TheScript=$0
saveIFS="$IFS"
IFS=$'\n'
files=($(find . -maxdepth 1 -newer $TheScript -print))
unset files[0]; #remove "."
tmpfile=$(mktemp temp.XXXXXX)
IFS="$saveIFS"
elements=${#files[@]}
if [ "$elements" -gt "0" ]; then
    tar cvfz $TarFile --exclude ".svn" --exclude ".swp" --exclude "Icon?" --exclude ".DS_Store" --exclude "$TarFile" "${files[@]}" && touch -r $tmpfile $TheScript
fi
rm $tmpfile;

相关内容