Docker文件夹自动备份至Telegram

2023-07-18 Views 备份 | 电报942字5 min read
featureimg

由来

使用的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
EOF