Docker文件夹自动备份至Telegram
由来
使用的VPS一直都是大厂的免费主机,所以一直有一个担忧,就是数据安全与备份。
之前利用ChatGPT撰写了一个自动备份并传到谷歌云盘的脚本,不过最近谷歌收紧了政策,一直备份失败。
脚本内容
考虑到Telegram的特殊性,于是修改了脚本内容。
#!/bin/bash
# 设置参数
backup_dir="/root/data/docker_data"
telegram_bot_token="60000:AAAAAjj4"
telegram_chat_id="561119"
log_file="/root/backup/backup.log"
# 获取当前日期
current_date=$(date +%Y%m%d)
echo "[$current_date] 开始备份" >> "$log_file"
# 压缩备份文件夹
backup_filename="backup_$(date +%Y%m%d).tar.gz"
if ! tar -czf "$backup_filename" "$backup_dir" > /dev/null 2>&1; then
echo "[$current_datetime] 备份失败" >> "$log_file"
message="备份失败:$backup_filename"
curl -s -X POST "https://api.telegram.org/bot$telegram_bot_token/sendMessage" \
-d chat_id="$telegram_chat_id" \
-d text="$message"
exit 1
fi
# 分割备份文件为较小的部分
split -b 40M "$backup_filename" "$backup_filename.part"
# 逐个发送分割的备份文件到 Telegram
for part_file in "$backup_filename".part*; do
upload_result=$(curl -s -F chat_id="$telegram_chat_id" -F document=@"$part_file" "https://api.telegram.org/bot$telegram_bot_token/sendDocument")
# 检查上传结果
if [[ $(echo "$upload_result" | jq -r '.ok') != "true" ]]; then
echo "[$current_datetime] 备份文件发送到 Telegram 失败" >> "$log_file"
exit 1
fi
# 提取文件信息
file_name=$(basename "$part_file")
message="已完成备份:$file_name"
curl -s -X POST "https://api.telegram.org/bot$telegram_bot_token/sendMessage" \
-d chat_id="$telegram_chat_id" \
-d text="$message"
done
# 发送备份情况到 Telegram
echo "[$current_datetime] 已完成备份:$backup_filename" >> "$log_file"
message="已完成备份:$backup_filename"
curl -s -X POST "https://api.telegram.org/bot$telegram_bot_token/sendMessage" \
-d chat_id="$telegram_chat_id" \
-d text="$message"
# 删除分割的备份文件
rm "$backup_filename".part*
rm "$backup_filename"
这个脚本的特别之处在于,它会将压缩后的备份文件拆为多个part文件(主要是电报API限制单文件不能超过50MB),然后通过Bot发送至Telegram。
取回与合并
通过电报客户端将part文件下载回本地(也可以不用管,毕竟Telegram永久存储),然后通过脚本合并成完整文件。
下面是合并part文件的脚本: merge_backup.ps1
chcp 65001
# 获取当前日期和时间
$currentDate = Get-Date -Format "yyyyMMdd"
# 获取当前目录下的所有分割文件
$partFiles = Get-ChildItem -Filter "*.part*" | Sort-Object Name
# 生成合并后的备份文件名
$backupFilename = "$currentDate.tar.gz"
# 创建空的备份文件
New-Item -ItemType File $backupFilename -Force | Out-Null
$totalFiles = $partFiles.Count
$processedFiles = 0
# 逐个读取分割文件内容,并写入到合并后的备份文件中
foreach ($partFile in $partFiles) {
$processedFiles++
$progressMessage = "Merging split files {0} / {1}" -f $processedFiles, $totalFiles
Write-Progress -Activity "Merge backup files" -Status $progressMessage -PercentComplete ($processedFiles / $totalFiles * 100)
$partContent = Get-Content $partFile.FullName -Encoding Byte -ReadCount 0
Add-Content -Path $backupFilename -Value $partContent -Encoding Byte
}
# 删除分割的部分文件
Remove-Item $partFiles -Force
# 输出合并完成的信息
Write-Host "Backup file merge completed:$backupFilename"
使用说明
将 merge_backup.ps1
文件放入parts文件夹中
右键,使用PowerShell运行
总结
此方案的优点在于
- 自动备份Docker文件夹等其他在远程服务器上的重要数据;
- 借助Telegram无限存储的优势,不用考虑备份盘的大小,且方便取回。
当然也有不足
- Telegram前端API限制单文件不能大于50MB,如果需要备份的文件太大,就会被拆分成很多个小part;
- 随之而来的就是,需要一个个另存到文件夹,然后运行脚本进行合并。
然而,数据无价嘛,就算麻烦点,也值得。
相应的,可以减少备份频率;
例如,通过crontab设置每10天备份一次。
crontab -e
0 0 */10 * * /root/backup/bback.sh