一天前,我编写了一个脚本,将我的整个数据库和所有 /var/www 文件备份到网络共享。这是我第一次尝试在 Linux 中编写脚本,总的来说,我认为它真的很酷。我想为我的备份脚本添加一项功能。目前,该脚本使用 rsync 覆盖备份目标上的任何现有数据。我希望它每次运行时都能创建一个唯一的完整备份。现在我让它每天晚上午夜运行。但是,我一次只希望有 15 个并发完整备份 - 因此一旦达到 15 个备份,我希望它开始删除较旧的备份。有人能给我指出正确的方向吗?
这是我当前的脚本:
#!/usr/bin/env bash
# Mount the share
smbmount //address/folder /mnt/folder -o credentials=/root/.smbpasswd
# Synchronize the Web folder
rsync --delete -C -v -a -r /var/www /mnt/folder
# Create a backup of all databases
mysqldump -uuser -ppassword --all-databases | gzip -9 > /root/backup/Databases.sql.zip
# Copy the backup to the backup folder
cp /root/backup/Databases.sql.zip /mnt/folder/Databases.sql.zip
echo "Backup complete!"
答案1
不要重新发明轮子——使用迪尔维什!
答案2
mv Databases.sql.zip sql-backup-`date +%Y-%m-%d`.zip
find *.zip -mtime +15 -exec rm {} \;
第一行将 zip 名称更改为基于当前日期的名称,第二行删除所有超过 15 天的 zip。
答案3
生成每周轮换的文件名的一种方法是使用date
来获取星期几的名称或数字:
TODAYS_BACKUP=$(date +'Databases-%a.sql.gz')
mysqldump --all-databases | gzip -9 > /root/backup/$TODAYS_BACKUP
这样,假设在备份之前的星期一,Databases-Sun.sql.gz 将是昨天的备份,Databases-Sat.sql.gz 将是前天的备份,等等。Databases-Mon.sql.gz 将是一周前的备份。(另一种思考方式是:Databases-XXX.sql.gz 来自最后的XXX.)
今天备份后,Databases-Mon.sql.gz将被覆盖。
这比未知的解决方案更为强大,因为如果由于某种原因一周内没有进行备份,他(她?)的解决方案将删除所有备份,而使用此解决方案,它们将保持不变。
要每 30 天左右轮换一次,您可以使用%d
十进制数表示月份中的日期。(在手册页中找出那些神秘的 % 转义符的含义strftime
。)
每 15 天轮换一次,嗯...你可以使用这个技巧:
date +'%s 86400 / 15 %% p' | dc
它计算自公元以来的天数,并取除以 15 后的余数。
缺点:1)看起来很复杂,2)没有给出 10 以下的前导 0...正如我所说:这是一种黑客行为。
附注:不要将密码放在脚本中,因为备份运行时可以从进程表中读取密码!至少将其放在 ~/.my.cnf 中,并使用适当的文件权限保护它!
第二点补充说明:使用 压缩的文件的正确后缀gzip
是.gz
。.zip
是指使用 WinZip、7zip 等压缩的文件。
第三点说明:如果 smbmount 由于某种原因失败(可能是服务器宕机),您的脚本会将备份写入挂载点所在的分区,这可能会填满您的根分区。防止这种情况的一个好方法是将chmod
挂载点设置为 000。
答案4
日期计算
以下是具体操作方法跳带有前导零的日期 hack:
rotation="0$(( ( $(date +%s) / 86400 ) % 15 ))" # add a leading zero
rotation="${rotation: -2}" # keep the rightmost 2 chars
正如您所见,没有必要使用dc
。
rsync 轮转
与其他人对数据库备份的指示类似,您可以使用以下命令创建多个 Web 目录备份rsync
:
rsync -Carv /var/www /mnt/folder/backup${rotation}/
这将创建一个名为“00”至“14”的目录,用于 15 个备份循环。您可以执行以下操作:
rm -rf /mnt/folder/backup${rotation}
事先将其清除。