51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

使用 Git 自动备份数据

Preface {#preface}

前两天不小心执行了rm -rf ~,OMG...

安装 git {#安装-git}

sudo apt install git

git config --global user.name 'Git用户名'

git config --global user.email "Git邮箱"

当然,在 Ubuntu 系统上一般都预先安装了。

新建 Git 仓库 {#新建-git-仓库}

giteeGithub上新建仓库,是不是空仓库都行,专门用来储存备份的数据。

需要将本地的 ssh 公钥文件配置到对应的,Git 仓库服务商上。没有公钥文件通过ssh-keygen -t rsa -b 4096生成一个,然后拷贝~/.ssh/id_rsa.pub文件中的内容到 Git 仓库服务商上即可。

注意:由于一般的 Git 仓库服务商都会限制仓库的大小,所以不适合备份太大的文件。

新建备份脚本 {#新建备份脚本}

在任意目录新建备份脚本backup.sh要保证脚本对脚本所在的目录有写权限

#!/bin/bash

# 定义变量,储存要备份的路径和对应的Git仓库地址
# 仓库地址可以多个或一个,多个的话要和 备份的路径 一一对应
backup_paths=(
  "/home/ubuntu/backupdir1"
  "/home/ubuntu/backupdir2"
)
git_repos=(
  "git@xxxx.com:user/backup1.git"
  "git@xxxx.com:user/backup2.git"
)

# 备份开始前的操作。
handle_before_backup() {
  # 比如可以用来停止 docker 容器,mysql 等
  # : 表示占位符,什么都不做,实际添加内容时你可以删掉它
  :
}

# 自定义处理打包方式,函数中当前所在路径是对应上传备份的 git 本地仓库中,
# 只需将你要备份的文件放到当前目录即可,可以是 tar,mysqldump 等
handle_backup() {
  # 备份路径 /home/xxx/backupdir
  local backup_path=$1
  # 备份目录名 backupdir
  local backup_dir=$2
  # 备份仓库地址 git@xxx.com:user/backup.git
  local git_repo=$3
  # 仓库名称 backup
  local repo_name=$4

  # 打包压缩
  tar czf "$backup_dir.tar.gz" -C "$backup_path" .
}

# 备份完成后的操作。
handle_after_backup() {
  # 比如可以用来启动 docker 容器,清除文件等。
  # : 表示占位符,什么都不做,实际添加内容时你可以删掉它
  :
}

# 在这之后的脚本内容就不需要更改了
# 存放备份地址的数组和仓库数组数量不一致,且仓库数组数量不唯一退出运行
if [ "${#git_repos[@]}" -ne 1 ] && [ "${#backup_paths[@]}" -ne "${#git_repos[@]}" ]; then
    echo "数组数量错误,退出运行!"
    exit
fi

# 获取脚本所在路径
script_path=$(readlink -f "$0")
backup_store_dir="${script_path}_store_dir"

# 使用条件判断备份文件存放目录是否存在
if [ ! -d "$backup_store_dir" ]; then
  mkdir "$backup_store_dir"
  # 检查 mkdir 命令的退出状态码
  if [ ! $? -eq 0 ]; then
    exit
  fi
fi

# 备份并上传函数
backup_and_upload() {
  local backup_path=$1
  local git_repo=$2

  echo -e "\n------------------ 开始备份 ${backup_path} ------------------\n"

  # 进入备份
  cd "$backup_store_dir"
  # 获取目录名
  local backup_dir=$(basename "$backup_path")
  # 使用git命令获取仓库名称
  local repo_name=$(basename "$git_repo" .git)
  
  # 判断仓库是否不存在
  if [ ! -d "$repo_name" ]; then
    git clone "$git_repo"

    # 检查 git clone 命令的退出状态码
    if [ ! $? -eq 0 ]; then
        # 克隆失败,手动初始化
        mkdir "$repo_name"
        cd "$repo_name"
        git init
        git remote add origin "$git_repo"
        cd ..
    fi

  fi

  # 目录不存在则退出函数
  if [ ! -d "$repo_name" ]; then
    exit
  else 
    cd "$repo_name"
  fi
  
  # 拉取
  git pull origin master

  # 自定义处理打包方式
  handle_backup "${backup_path}" "${backup_dir}" "${git_repo}" "${repo_name}"
  
  # # 暂存、提交、推送
  git add .
  git commit -m $(date "+%Y-%m-%d~%H:%M:%S_${backup_dir}_数据备份")
  git push -u origin master
}

# 调用备份开始前操作
handle_before_backup

# 循环读取备份路径对应的Git仓库地址,并执行备份并上传函数
for ((i=0; i<${#backup_paths[@]}; i++)); do
  if [ "${#git_repos[@]}" -eq 1 ]; then
    backup_and_upload "${backup_paths[i]}" "${git_repos[0]}"
  else
    backup_and_upload "${backup_paths[i]}" "${git_repos[i]}"
  fi
done

# 调用备份完成后操作
handle_after_backup

修改脚本中的backup_paths变量为你需要备份的文件夹或文件路径。

修改脚本中的git_repos变量为你要备份到的仓库地址,需要和上面的backup_paths一一对应,或者只设置一个,这样所有的备份文件都会上传到这个仓库中。如果只设置一个仓库要注意生成的备份文件名称不要重复,否则后面的备份文件会覆盖掉前面的备份文件。

修改handle_backup函数内容,选择要备份的形式。比方说一些静态文件可用tar命令打包,而数据库文件则不能直接用tar打包,这样可能会造成数据错乱的现象,因为tar是以递归的形式一个一个打包的,这种情况可以在handle_backup函数中使用mysqldump工具生成备份文件,或者在handle_backup函数中先停止mysql运行,然后执行tar命令,等打包成功后再启动mysql服务。

最后为脚本赋予可执行权限chmod +x backup.sh

设置定时任务 {#设置定时任务}

一般最好用root账号来执行定时任务,以免发生权限不足的问题。如果确保没问题可忽略。

sudo su

crontab -e

设置每天凌晨 4 点执行一次,注意脚本路径要写绝对路径。

00 04 * * * /xxx/xxx/backup.sh

提示 {#提示}

github 和 gitee 个人免费版的仓库单文件大小都有限制,为 100MB,对于这种情况可以使用splitcat命令。

splitcat 是在 Unix/Linux 系统中常用的命令,它们分别用于拆分文件和合并文件的操作。

split 命令用于将一个大文件拆分成若干个较小的文件。其基本语法如下:

split [选项] 文件 [前缀]
  • 选项:可以指定一些参数,如文件大小、行数等。常见的选项有 -b(按字节拆分)、-l(按行数拆分)等。
  • 文件:需要拆分的大文件。
  • 前缀:生成的小文件的前缀名。

示例:

split -b 10M docker-data.tar.gz backup

这个例子将 docker-data.tar.gz 按照 10MB 的大小拆分成多个文件,文件名以 backup 作为前缀。

cat 命令用于连接文件内容并打印到标准输出,也可以用于创建新文件。其基本语法如下:

cat [选项] [文件]
  • 选项:可以指定一些参数,如 -n(显示行号)、-b(非空行显示行号)等。
  • 文件:要连接的文件列表。

示例:

cat backup* > docker-data.tar.gz

这个例子将以 backup 开头文件的内容连接,并将结果输出到 docker-data.tar.gz 文件中。

所以通过此方法就可以将大文件分成多个小文件上传,等需要恢复备份时用cat将分片合成一个即可。

还需要注意的点是仓库的总容量也是有上限的,因此要备份的文件是中大型文件需要定时清空或新建一个仓库。

参考资料 {#参考资料}

赞(2)
未经允许不得转载:工具盒子 » 使用 Git 自动备份数据