使用 logrotate 的简单解决方案

使用 logrotate 的简单解决方案

我正在寻找一个非常基本的备份脚本/包,用于备份我 Ubuntu 服务器上的目录。目前,我正在使用如下的 cronjob:

0 5 * * 1 sudo tar -Pzcf /var/backups/home.tgz /home/

但我想要一个解决方案,它可以在文件名中添加时间戳,并且不会覆盖旧备份。当然,这会慢慢淹没我的驱动器,因此需要自动删除旧备份(例如超过 2 个月的备份)。

干杯,丹尼斯


更新:我决定将赏金授予 -solution,logrotate因为它很简单。但也非常感谢所有其他回答者!

答案1

使用 logrotate 的简单解决方案

如果您希望保持简单并且不编写脚本,只需保留当前的 ​​cronjob 并为其配置 logrotate 规则。

为此,请将以下内容放入名为的文件中/etc/logrotate.d/backup-home

/var/backups/home.tgz {
    weekly
    rotate 8
    nocompress
    dateext
}

从现在开始,每次运行 logrotate(通常每天早上 6:25 左右运行),它都会检查是否适合轮换,如果适合,则将其重命名home.tgz为另一个文件并添加时间戳。它会保留 8 个副本,因此您大约有两个月的历史记录。

您可以使用以下方式自定义时间戳日期格式选项,请参见logrotate(8)

因为您的备份作业在凌晨 5 点运行,而 logrotate 在凌晨 6 点 25 分运行,所以您应该确保您的 tar 备份在 1 小时 25 分钟内运行良好(我想无论如何它会快得多)。

答案2

这是我使用的脚本(的变体)(/home/pduck/bup.sh):

#!/usr/bin/env bash

src_dir=/home/pduck
tgt_dir=/tmp/my-backups
mkdir -p $tgt_dir

# current backup directory, e.g. "2017-04-29T13:04:50";
now=$(date +%FT%H:%M:%S) 

# previous backup directory
prev=$(ls $tgt_dir | grep -e '^....-..-..T..:..:..$' | tail -1); 

if [ -z "$prev" ]; then
    # initial backup
    rsync -av --delete $src_dir $tgt_dir/$now/
else
    # incremental backup
    rsync -av --delete --link-dest=$tgt_dir/$prev/ $src_dir $tgt_dir/$now/
fi

exit 0;

在我的例子中,它用于rsync将文件从我的主目录本地复制到备份位置/tmp/my-backups。在该目标目录下创建一个带有当前时间戳的目录,例如,/tmp/my-backups/2018-04-29T12:49:42在该目录下放置当天的备份。

当脚本再次运行时,它会注意到已经有一个目录/tmp/my-backups/2018-04-29T12:49:42(它会选择与时间戳模式匹配的“最新”目录)。然后它会执行命令,rsync但这次使用--link-dest=/tmp/my-backups/2018-04-29T12:49:42/开关指向上一个备份。

这是进行增量备份的实际要点:

使用--link-dest=…rsync 不会复制与 link-dest 目录中的文件相比没有变化的文件。相反,它只会创建硬链接当前文件和先前文件之间。

当您运行此脚本 10 次时,您将获得 10 个具有不同时间戳的目录,每个目录都保存了当时文件的快照。您可以浏览目录并恢复所需的文件。

管理也非常简单:只需rm -rf保留您不想保留的时间戳目录。这不会删除较旧、较新或未更改的文件,只会删除(减少)硬链接。例如,如果您有三代:

  • /tmp/my-backups/2018-04-29T...
  • /tmp/my-backups/2018-04-30T...
  • /tmp/my-backups/2018-05-01T...

并删除第二个目录,那么你就会丢失快照但文件仍然在第一个或第三个目录中(或两者)。

我放入了一个 cronjob,/etc/cron.daily内容如下:

#!/bin/sh
/usr/bin/systemd-cat -t backupscript -p info /home/pduck/bup.sh

给这个文件命名backup或者类似的东西chmod +x,但是忽略后缀.sh(此时不会运行)。由于/usr/bin/systemd-cat -t backupscript -p info您可以通过 来查看进度journalctl -t backupscript

请注意,由于硬链接,此rsync解决方案要求目标目录位于文件系统上。ext4

答案3

对 cron 命令进行一些编辑后,您就可以向文件名添加时间戳:

0 5 * * 1 sudo tar -Pzcf /var/backups/home_$(date "+%Y-%m-%d_%H-%M-%S").tgz /home/

至于清理,我发现了一个很棒的单行脚本这里我根据你的情况进行了调整:

find . -type f -name 'home_*.tgz' -exec sh -c 'bcp="${1%_*}"; bcp="${bcp#*_}"; [ "$bcp" "<" "$(date +%F -d "60 days ago")" ] && rm "$1"' 0 {} \;

您可以将上述命令添加到另一个 cron 作业中,它将删除超过 60 天的备份。HTH

答案4

以下是我的每日备份脚本(由 cron 调用)的部分解决方案:将 Linux 配置、脚本和文档备份到 Gmail。完整脚本不合适,因为:

  • 它包含目标/home/me/*文件,但跳过了/home/FireFox、Chrome 和其他应用程序使用的 1 GB 的重要文件,我对备份这些文件不感兴趣。
  • 它包含对我来说很重要但对你来说不重要的文件/etc/cron*,,,,,,,等。/etc/system*/lib/systemd/system-sleep/etc/rc.local/boot/grub/usr/share/plymouth/etc/apt/trusted.gpg
  • 它每天早上都会将备份通过电子邮件发送到我的 gmail.com 帐户,以供异地备份。您的备份不仅在现场,而且在同一台机器上。

以下是相关脚本,您可以调整其中的部分内容:

#!/bin/sh
#
# NAME: daily-backup
# DESC: A .tar backup file is created, emailed and removed.
# DATE: Nov 25, 2017.
# CALL: WSL or Ubuntu calls from /etc/cron.daily/daily-backup
# PARM: No parameters but /etc/ssmtp/ssmtp.conf must be setup

# NOTE: Backup file name contains machine name + Distro
#       Same script for user with multiple dual boot laptops
#       Single machine should remove $HOSTNAME from name
#       Single distribution should remove $Distro

sleep 30 # Wait 30 seconds after boot

# Running under WSL (Windows Subsystem for Ubuntu)?
if cat /proc/version | grep Microsoft; then
    Distro="WSL"
else
    Distro="Ubuntu"
fi

today=$( date +%Y-%m-%d-%A )
/mnt/e/bin/daily-backup.sh Daily-$(hostname)-$Distro-backup-$today

我的 gmail.com 只占用了 35%(总共 15 GB),因此我的每日备份可以运行一段时间,之后我才需要删除文件。但我不会采用“删除所有比 xxx 更早的文件”的理念,而是采用以下概述的祖父-父亲-儿子策略:我有必要保留备份记录吗?。 总之:

  • 周一至周日(每日备份),14 天后清除
  • 周日备份(每周备份)8 周后清除
  • 每月最后一天的备份(每月备份)在 18 个月后清除
  • 每年最后一天的备份(年度备份)永久保存

我的清除过程会变得复杂,因为我必须学习 Python 并安装一个 Python 库来管理 gmail 文件夹。

如果您不想要代际备份并想要清除超过 2 个月的文件,那么这个答案会有所帮助:通过 bash 脚本查找不删除文件夹中的文件

总之:

DAYS_TO_KEEP=60
find $BACKUP_DIR -maxdepth 1 -mtime +"$DAYS_TO_KEEP" -exec rm -rf {} \;

相关内容