用于增量备份的 Linux 备份实用程序

use*_*323 18 linux backup software-rec

我正在寻找具有增量备份的备份实用程序,但方式更复杂。

我试过 rsync,但它似乎无法做我想做的事,或者更有可能的是,我不知道如何让它做到这一点。

所以这是我想用它实现的一个例子。我有以下文件:

testdir
??? picture1
??? randomfile1
??? randomfile2
??? textfile1
Run Code Online (Sandbox Code Playgroud)

我想运行备份实用程序并基本上在不同目录中创建所有这些文件的存档(或 tarball):

$ mystery-command testdir/ testbak
testbak
??? 2020-02-16--05-10-45--testdir.tar
Run Code Online (Sandbox Code Playgroud)

现在,假设第二天,我添加了一个文件,使我的结构如下所示:

testdir
??? picture1
??? randomfile1
??? randomfile2
??? randomfile3
??? textfile1
Run Code Online (Sandbox Code Playgroud)

现在,当我运行神秘命令时,我将获得当天的另一个 tarball:

$ mystery-command testdir/ testbak
testbak
??? 2020-02-16--05-10-45--testdir.tar
??? 2020-02-17--03-24-16--testdir.tar
Run Code Online (Sandbox Code Playgroud)

这里的踢球者:我想备份实用程序检测到的事实是picture1randomfile1randomfile2textfile1上次备份没有改变,和新的/更改的文件只备份,在这种情况下randomfile3,这样的:

tester@raspberrypi:~ $ tar -tf testbak/2020-02-16--05-10-45--testdir.tar 
testdir/
testdir/randomfile1
testdir/textfile1
testdir/randomfile2
testdir/picture1
tester@raspberrypi:~ $ tar -tf testbak/2020-02-17--03-24-16--testdir.tar 
testdir/randomfile3
Run Code Online (Sandbox Code Playgroud)

所以作为最后一个例子,假设第二天我改变了textfile1,并添加了picture2picture3

$ mystery-command testdir/ testbak
testbak/
??? 2020-02-16--05-10-45--testdir.tar
??? 2020-02-17--03-24-16--testdir.tar
??? 2020-02-18--01-54-41--testdir.tar
tester@raspberrypi:~ $ tar -tf testbak/2020-02-16--05-10-45--testdir.tar 
testdir/
testdir/randomfile1
testdir/textfile1
testdir/randomfile2
testdir/picture1
tester@raspberrypi:~ $ tar -tf testbak/2020-02-17--03-24-16--testdir.tar 
testdir/randomfile3
tester@raspberrypi:~ $ tar -tf testbak/2020-02-18--01-54-41--testdir.tar 
testdir/textfile1
testdir/picture2
testdir/picture3
Run Code Online (Sandbox Code Playgroud)

使用这个系统,我将通过仅备份每个备份之间的增量更改来节省空间(显然主备份包含所有初始文件),并且我将备份增量更改,例如,如果我进行了更改在第 2 天,并在第 3 天再次更改相同的内容,我仍然可以获取第 2 天更改的文件,但在第 3 天更改之前。

我认为这有点像 GitHub 的工作方式:)

我知道我可能会创建一个运行差异的脚本,然后根据结果选择要备份的文件(或者更有效,只需获取校验和并进行比较),但我想知道是否有任何实用程序可以做到这一点容易一点:)

JoL*_*JoL 12

我试过 rsync,但它似乎无法做我想做的事,或者更有可能的是,我不知道如何让它做到这一点。

我知道我可能会创建一个运行差异的脚本,然后根据结果选择要备份的文件(或者更有效,只需获取校验和并进行比较),但我想知道是否有任何实用程序可以做到这一点容易一点:)

rsync正是基于差异复制的程序。默认情况下,它仅在上次修改时间或大小不同时才进行复制,但它甚至可以通过校验和与-c.

这里的问题是您正在tar备份。如果你不这样做,这会变得更容易。我什至不知道你为什么要这样做。如果你压缩它们可能是有意义的,但你甚至没有这样做。

增量备份维基百科文章有一个示例rsync命令,大致如下:

rsync -va \
  --link-dest="$dst/2020-02-16--05-10-45--testdir/" \
  "$src/testdir/" \
  "$dst/2020-02-17--03-24-16--testdir/"
Run Code Online (Sandbox Code Playgroud)

它的作用是硬链接上一个备份中的文件,当它们与源文件没有变化时。还有--copy-dest,如果你想让它,而不是复制(它仍然较快时,$dst是远程或更快的驱动器上)。

如果您使用带有子卷(如 btrfs)的文件系统,您还可以在 rsync 之前从之前的备份中创建快照。快照是即时的,不会占用额外的空间[1]。

btrfs subvolume snapshot \
  "$dst/2020-02-16--05-10-45--testdir" \
  "$dst/2020-02-17--03-24-16--testdir"
Run Code Online (Sandbox Code Playgroud)

或者,如果您使用的是支持引用链接的文件系统,那么您也可以这样做。Reflinks 是通过创建一个新的 inode 但引用与源文件相同的块来完成的,实现 COW 支持。它仍然比普通副本快,因为它不读写数据,也不占用额外的空间[1]。

cp --reflink -av \
  "$dst/2020-02-16--05-10-45--testdir" \
  "$dst/2020-02-17--03-24-16--testdir"
Run Code Online (Sandbox Code Playgroud)

无论如何,一旦做了类似的事情,你就可以做一个常规rsync来复制差异:

rsync -va \
  "$src/testdir/" \
  "$dst/2020-02-17--03-24-16--testdir/"
Run Code Online (Sandbox Code Playgroud)

但是,您可能想要添加--delete,这会导致 rsync 从目标中删除源中不再存在的文件。

另一个有用的选项是-i--itemize-changes。它产生简洁的、机器可读的输出,描述 rsync 正在做的更改。我通常添加该选项和管道,如:

rsync -Pai --delete \
  "$src/testdir/" \
  "$dst/2020-02-17--03-24-16--testdir/" \
|& tee -a "$dst/2020-02-17--03-24-16--testdir.log"
Run Code Online (Sandbox Code Playgroud)

通过易于使用的grep文件记录更改。该|&是管标准输出和标准错误。

-P很短的--partial--progress--partial保留部分传输的文件,但更重要的是--progress报告每个文件的进度。

这与使用 tar 归档更改相比如​​何

上述解决方案导致目录似乎包含所有内容。即使是这种情况,对于任何数量/频率的备份,它们占用的空间量与仅更改的纯 tar 存档大致相同。这是因为硬链接、引用链接和快照的工作方式。创建备份时带宽的使用也是相同的。

优点是:

  • 使用 rsync 可以轻松恢复备份并且速度更快,因为 rsync 只会传输备份中的差异。
  • 如果需要,它们更易于浏览和修改。
  • 文件删除可以自然地编码为文件在新备份中的缺失。当使用 tar 档案时,人们不得不求助于黑客,比如删除一个文件foo、标记它foo.DELETED或做一些复杂的事情。例如,我从未使用过双重性,但查看其文档,似乎它通过在新 tar 中添加一个同名的空文件并将文件的原始签名保存在单独的 .sigtar 文件中来对删除进行编码。我想它将原始签名与空文件的签名进行比较,以区分文件删除和对实际空文件的更改。

如果仍然希望将每个备份设置为仅保存不同(添加或修改)的文件,则可以使用上述--link-dest解决方案,然后使用以下内容删除硬链接:

find $new_backup -type f ! -links 1 -delete
Run Code Online (Sandbox Code Playgroud)

[1] 严格来说,它们确实以重复元数据的形式使用了额外的空间,例如文件名等。但是,我认为任何人都会认为这无关紧要。


小智 11

虽然tar确实有增量模式,但有一些更全面的工具可以完成这项工作:

它们不仅支持增量备份,还可以轻松配置需要进行完整备份的计划。例如在duplicity:duplicity --full-if-older-than 1M将确保已运行完整备份。它们还支持及时返回到特定文件,使用纯 tar,您必须遍历所有增量文件,直到找到包含正确文件的文件。

此外,它们确实支持加密和上传到各种后端(如 sftp、blob 存储等)。显然,如果您进行加密,请不要忘记将您的密钥备份到辅助备份中!

另一个重要方面是您可以验证备份的完整性,确保您可以恢复,例如使用duplicity verify.

我会对基于 git 的备份策略提出负面建议。大型还原需要很长时间。

  • @Kaithar,你所有的备份都属于我们,真的:-P (2认同)

小智 6

你为什么不考虑git自己?

您描述的策略,在一次完整备份和两次增量备份之后,在您继续时会变得复杂。这是很容易犯错误,而且可以得到非常低效的,这取决于变化。必须有一种轮换,即您不时进行新的完整备份 - 然后您是否要保留旧的?


给定一个包含一些项目(文件和子目录)的工作目录“testdir” ,默认情况下为数据创建一个隐藏的子目录。那将用于本地的附加版本控制功能。对于备份,您可以将其存档/复制到介质或通过网络克隆它。git.git

您获得的修订控制(无需请求)是 git 差异存储的副作用。

您可以省略所有分叉/分支等。这意味着您有一个名为“master”的分支。

在提交之前(实际上是写入 git archive/repo),您必须为配置文件配置一个最小用户。那么你应该首先在一个子目录(可能是 tmpfs)中学习和测试。有时,Git 和 tar 一样棘手。

无论如何,正如评论所说:备份很容易,难的是恢复。


git 的缺点只是小开销/矫枉过正。

优点是:git跟踪内容和文件名。它只保存必要的,基于差异(至少对于文本文件)。


例子

我在一个目录中有 3 个文件。之后git initgit add .git commit我有一个260K.git目录。

然后我cp -r .git /tmp/abpic.git(保存备份的好地方:)。我rm是154K jpg,也换了一个文本文件。我也rm -r .git

  ]# ls
    atext  btext

  ]# git --git-dir=/tmp/abpic.git/ ls-files
    atext
    btext
    pic154k.jpg
Run Code Online (Sandbox Code Playgroud)

在恢复文件之前,我可以获得精确的差异:

]# git --git-dir=/tmp/abpic.git/ status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   atext
        deleted:    pic154k.jpg

no changes added to commit (use "git add" and/or "git commit -a")
Run Code Online (Sandbox Code Playgroud)

在这里,我想按照git restore提示进行操作。

之后git --git-dir=/tmp/abpic.git/ restore \*

]# ls -st
total 164
  4 atext  156 pic154k.jpg    4 btext
Run Code Online (Sandbox Code Playgroud)

jpeg 回来了,文本文件btext没有更新(保留时间戳)。中的修改atext被覆盖。

要重新组合 repo 和(工作)目录,您只需将其复制回来即可。

]# cp -r /tmp/abpic.git/ .git
]# git status
On branch master
nothing to commit, working tree clean
Run Code Online (Sandbox Code Playgroud)

当前目录中的文件与.git存档相同(在 之后restore)。将显示新更改,并且可以添加和提交,无需任何计划。您只需要将其存储到另一个介质中,以用于备份目的。


修改文件后,您可以使用statusdiff

]# echo more >>btext 

]# git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   btext

no changes added to commit (use "git add" and/or "git commit -a")

]# git diff
diff --git a/btext b/btext
index 96b5d76..a4a6c5b 100644
--- a/btext
+++ b/btext
@@ -1,2 +1,3 @@
 This is file b
 second line
+more
#]
Run Code Online (Sandbox Code Playgroud)

就像git知道文件“btext”中的“+more”一样,它也只会增量存储该行。

git add .(或git add btext)status命令从红色切换到绿色之后,它commit会为您提供信息。

]# git add .
]# git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   btext

]# git commit -m 'btext: more'
[master fad0453] btext: more
 1 file changed, 1 insertion(+)
Run Code Online (Sandbox Code Playgroud)

你可以真正了解内容,不知何故:

]# git ls-tree @
100644 blob 321e55a5dc61e25fe34e7c79f388101bd1ae4bbf    atext
100644 blob a4a6c5bd3359d84705e5fd01884caa8abd1736d0    btext
100644 blob 2d550ffe96aa4347e465109831ac52b7897b9f0d    pic154k.jpg
Run Code Online (Sandbox Code Playgroud)

然后是前 4 个十六进制哈希数字

]# git cat-file blob a4a6
This is file b
second line
more
Run Code Online (Sandbox Code Playgroud)

要通过一次提交回到过去,它是:

]# git ls-tree @^
100644 blob 321e55a5dc61e25fe34e7c79f388101bd1ae4bbf    atext
100644 blob 96b5d76c5ee3ccb7e02be421e21c4fb8b96ca2f0    btext
100644 blob 2d550ffe96aa4347e465109831ac52b7897b9f0d    pic154k.jpg

]# git cat-file blob 96b5
This is file b
second line
Run Code Online (Sandbox Code Playgroud)

btext 的 blob 在上次提交之前具有不同的哈希值,其他的具有相同的哈希值。

概述是:

]# git log
commit fad04538f7f8ddae1f630b648d1fe85c1fafa1b4 (HEAD -> master)
Author: Your Name <you@example.com>
Date:   Sun Feb 16 10:51:51 2020 +0000

    btext: more

commit 0bfc1837e20988f1b80f8b7070c5cdd2de346dc7
Author: Your Name <you@example.com>
Date:   Sun Feb 16 08:45:16 2020 +0000

    added 3 files with 'add .'
Run Code Online (Sandbox Code Playgroud)

您提交的不是手动添加时间戳的 tar 文件,而是带有消息和日期(以及作者)。逻辑上附加到这些提交的是文件列表和内容。

Simplegit比 复杂 20% tar,但您可以从中获得 50% 的决定性功能。


我想进行 OP 的第三次更改:更改一个文件以及两个新的“图片”文件。我有,但现在我有:

]# git log
commit deca7be7de8571a222d9fb9c0d1287e1d4d3160c (HEAD -> master)
Author: Your Name <you@example.com>
Date:   Sun Feb 16 17:56:18 2020 +0000

    didn't add the pics before :(

commit b0355a07476c8d8103ce937ddc372575f0fb8ebf
Author: Your Name <you@example.com>
Date:   Sun Feb 16 17:54:03 2020 +0000

    Two new picture files
    Had to change btext...

commit fad04538f7f8ddae1f630b648d1fe85c1fafa1b4
Author: Your Name <you@example.com>
Date:   Sun Feb 16 10:51:51 2020 +0000

    btext: more

commit 0bfc1837e20988f1b80f8b7070c5cdd2de346dc7
Author: Your Name <you@example.com>
Date:   Sun Feb 16 08:45:16 2020 +0000

    added 3 files with 'add .'
]# 
Run Code Online (Sandbox Code Playgroud)

那么,在下午 6 点前不久,Your Name Guy 在他的两次提交中究竟做了什么?

最后一次提交的详细信息是:

]# git show
commit deca7be7de8571a222d9fb9c0d1287e1d4d3160c (HEAD -> master)
Author: Your Name <you@example.com>
Date:   Sun Feb 16 17:56:18 2020 +0000

    didn't add the pics before :(

diff --git a/picture2 b/picture2
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/picture2
@@ -0,0 +1 @@
+1
diff --git a/picture3 b/picture3
new file mode 100644
index 0000000..0cfbf08
--- /dev/null
+++ b/picture3
@@ -0,0 +1 @@
+2
]# 
Run Code Online (Sandbox Code Playgroud)

并检查倒数第二次提交,其消息宣布两张图片:

]# git show @^
commit b0355a07476c8d8103ce937ddc372575f0fb8ebf
Author: Your Name <you@example.com>
Date:   Sun Feb 16 17:54:03 2020 +0000

    Two new picture files
    Had to change btext...

diff --git a/btext b/btext
index a4a6c5b..de7291e 100644
--- a/btext
+++ b/btext
@@ -1,3 +1 @@
-This is file b
-second line
-more
+Completely changed file b
]# 
Run Code Online (Sandbox Code Playgroud)

发生这种情况是因为我尝试git commit -a使用快捷方式git add .,并且这两个文件是新的(未跟踪)。它以红色显示git status,但正如我所说,git 并不比 tar 或 unix 更棘手。


“你的新人只知道你需要什么,但我知道你想要什么”(或者反过来。重点是它并不总是一样的)

  • @user361323 如何_付费_ git _free_?你是说 Git**Hub** 吗?我想我说明了如何使用基本的 git 命令在本地获取类似 github 的信息。就像 tar 一样,但你得到的是 GIT DIR 而不是 TAR 文件。小缺点,大优点。--- 顺便说一句,在所有这些添加、提交、恢复、显示之后,我喜欢你直接回答我的介绍性问题。比较、状态和日志记录。 (2认同)

jca*_*ron 6

我建议您看一下Borg Backup

这将处理以下备份:

  • 已进行重复数据删除。这间接使其成为差异备份,但具有更多优点:

    • 它将处理同一文件的多个副本
    • 或者甚至是不同文件中的相同块
    • 将有助于处理不断增长的文件(如日志)
    • 将有助于重命名的文件(例如某些轮换设置中的日志)
  • 被压缩

  • 可以像常规远程文件系统一样安装(您可以安装以前的任何备份)

它将使用“每日备份一周、每周备份一个月、每月备份一年”等规则来管理旧备份的修剪。

设置和使用非常简单。


Ang*_*elo 5

更新:

请在此处查看一些注意事项: 是否可以使用 tar 进行完整系统备份?

根据那个答案,使用 tar 恢复增量备份容易出错,应该避免。除非您完全确定可以在需要时恢复数据,否则请勿使用以下方法。


根据文档,您可以使用 -g/--listed-incremental 选项来创建增量 tar 文件,例如。

tar -cg data.inc -f DATE-data.tar /path/to/data
Run Code Online (Sandbox Code Playgroud)

然后下次做类似的事情

tar -cg data.inc -f NEWDATE-data.tar /path/to/data
Run Code Online (Sandbox Code Playgroud)

其中 data.inc 是您的增量元数据,而 DATE-data.tar 是您的增量存档。

  • 祝你好运。无论您最终做什么,都不要忘记测试您的还原过程。 (3认同)
  • 这是一个众所周知的 gnu tar 功能,当您尝试恢复增量时经常失败。最好使用 `star`。 (3认同)

sch*_*ily 5

我推荐star增量备份,因为star已经过验证可以可靠地支持增量转储恢复。后者在重命名目录时不适用于 GNU tar,即使它已被宣传了 28 年。

请阅读http://schlytools.sourceforge.net/man/man1/star.1.html 上star手册页

关于增量备份的部分当前从第 53 页开始。

要下载源代码,请从http://sourceforge.net/projects/schilytools/files/获取 schilytools tarball

检查是否可以使用 tar 进行完整系统备份?用于验证 GNU tar 错误。