一台云服务器Ubuntu篇:8、数据备份

免费VPS,不知道什么时候没有了,数据自动备份与上传很重要。

find -mtime +5/5/-5的理解


最右边为当前时,+5 代表大于等于 6 天前的档案名, -5 代表小于等于 5 天内的档案名,5 则是代表 5-6 那一天的档案名。

sudo vim /root/backups.sh

Bash
#!/bin/bash

# update 2025/10/30
<<RequirementsDescription
1、可选:chmod u+x /root/backups.sh && chown -R root:adm /data/OCI_Ubuntu
2、以root用户运行,用于备份网站与mariadb数据库。
3、apt install tree 7zip 
   rclone建议从网站下载最新发行版本,apt是1.60 
   wget https://downloads.rclone.org/v1.71.2/rclone-v1.71.2-linux-amd64.deb
4、自动创建目录结构:${bakRootDIR}
RequirementsDescription

<<IfDescription
# 运算符:https://www.runoob.com/linux/linux-shell-basic-operators.html
if [ $a == $b ]; then echo "a 等于 b";
  elif [ $a -gt $b ]; then echo "a 大于 b"; 
  elif [ $a -lt $b ]; then echo "a 小于 b";
  else echo "没有符合的条件"
fi
# shell教程:https://blog.t725.cn/?p=1259 https://www.runoob.com/linux/linux-shell.html
# 多条件ADN:if [condition1 -a condition2] 或 if [condition1] && [ condition2 ]
# 多条件 OR:if [condition1 -o condition2] 或 if [condition1] || [ condition2 ]
IfDescription

toDay=$(date '+%y%m%d')
currentMonth=$(date '+%y%m')
passWD='Abcd#123'
bakRootDIR=/data/OCI_Ubuntu
# 文件夹不存在,则创建
if [ ! -d ${bakRootDIR}/conf ]; then mkdir -p ${bakRootDIR}/conf; fi
if [ ! -d ${bakRootDIR}/dump ]; then mkdir -p ${bakRootDIR}/dump; fi

# 备份配置文件
function backupConfigFiles {
    echo ======= $(date '+%Y-%m-%d %H:%M:%S') backupConfigFiles =======
    confBakList="/etc/php/8.3/fpm/pool.d/www.conf /etc/php/8.3/cli/php.ini /etc/nginx/nginx.conf /etc/nginx/sites-enabled/ /etc/letsencrypt/archive/blog.t725.cn/ /etc/mysql/my.cnf /etc/mysql/mariadb.conf.d/50-server.cnf $0"
    7za a -t7z -p${toDay} -spf2 ${bakRootDIR}/conf/${toDay}_conf.7z ${confBakList}
    find ${bakRootDIR}/conf -maxdepth 1 -mtime +10 -type f -name "*_conf.7z" -delete
    #find ${bakRootDIR}/conf/ -type f -name "*" -exec chmod u-x,g-x,o-x {} \;
    echo ======= $(date '+%Y-%m-%d %H:%M:%S') backupLogFiles =======
    logBakList="/var/log/nginx/"
    7za a -t7z -p${toDay} ${bakRootDIR}/dump/${toDay}_log.7z ${logBakList}
    find ${bakRootDIR}/dump -maxdepth 1 -mtime +10 -type f -name "*_log.7z" -delete
}

# 调用格式:clear7zFile 目录 文件名,作用:在{目录}下,修改时间在最近N天内,有大于M个的{文件名}时,则删除N天之前的。 
function clear7zFile {
    echo ======= $(date '+%Y-%m-%d %H:%M:%S') clear7zFile $1/$2 =======
    # 查找当前目录下(不包含子目录),修改时间在最近7天内,有多少个备份文件
    FileQty=$(find $1 -maxdepth 1 -mtime -7 -type f -name "$2" | wc -l)
    if [ "${FileQty}" -gt 5 ]
    then 
        # 查找当前目录下(不包含子目录),修改时间在7天之前的所有普通文件,再通过[-exec <CMD> \;]删除;注意,<CMD>左右都有空格,{}代表被找到文件。
        find $1 -maxdepth 1 -mtime +6 -type f -name "$2" -exec -delete
    fi
}

# 备份文件,调用格式:backupFiles 目标目录 源目录
function backupFiles {
    echo ======= $(date '+%Y-%m-%d %H:%M:%S') backupFiles $1 $2 =======
    targetDIR=$1
    sourceDIR=$2
    # 删除要使用的文件名
    rm -f ${targetDIR}/${toDay}_file.7z
    7za a -t7z -p${passWD} ${targetDIR}/${toDay}_file.7z ${sourceDIR}
}

# 备份数据库,调用格式:backupDb 数据库名 7z保存目录 sql临时目录
# -- 准备备份账号
# MariaDB [(none)]> CREATE USER 'dbBak'@'localhost' IDENTIFIED BY "w4maDZwTt"; 
# MariaDB [(none)]> GRANT select,show view,event,trigger,lock tables ON *.* TO 'dbBak'@'localhost';
function backupDb {
    echo ======= $(date '+%Y-%m-%d %H:%M:%S') backupDb $1 $2 $3 =======
    dbName=$1
    dbUser=dbBak
    dbPassWD="w4maDZwTt"
    targetDIR=$2
    dumpDIR=$3
    rm -f ${dumpDIR}/${dbName}_${toDay}.sql
    mariadb-dump -hlocalhost -P3306 -u${dbUser} -p${dbPassWD} --events --routines --triggers --databases ${dbName} > ${dumpDIR}/${dbName}_${toDay}.sql
    rm -f ${targetDIR}/${toDay}_db.7z
    7za a -t7z -p${passWD} ${targetDIR}/${toDay}_db.7z ${dumpDIR}/${dbName}_${toDay}.sql
    rm -f ${dumpDIR}/${dbName}_${toDay}.sql
}

#备份日志,调用格式:bakLogFile 提示文字 是否执行tree
function bakLogFile {
    echo ======= $1 $(date '+%Y-%m-%d %H:%M:%S') =======
    echo ======= $1 $(date '+%Y-%m-%d %H:%M:%S') ======= >> ${bakRootDIR}/dump/backup_${currentMonth}.log
    if [ $2 ]; then tree -sh ${bakRootDIR} >> ${bakRootDIR}/dump/backup_${currentMonth}.log; fi
}

# 准备备份:$1不为空,tree输出到文件
if [ ! -d ${bakRootDIR} ]; then mkdir -p ${bakRootDIR}; fi

if [ $1 ]; then bakLogFile "Start backups" tree; fi
# 执行备份:/data/www/wordPress 337MiB,其中 wp-content/uploads/wp-statistics/GeoLite2-City.mmdb 55M;7za 耗时5:15,压缩后134MiB。
backupConfigFiles
if [ ! -d ${bakRootDIR}/wordPress ]; then mkdir -p ${bakRootDIR}/wordPress; fi
clear7zFile ${bakRootDIR}/wordPress *_file.7z
backupFiles ${bakRootDIR}/wordPress /data/www/wordPress
clear7zFile ${bakRootDIR}/wordPress *_db.7z
backupDb WordPress ${bakRootDIR}/wordPress ${bakRootDIR}/dump
# 备份结束:$1不为空,tree输出到文件
if [ $1 ]; then bakLogFile "End backups" tree; fi

# 双向同步准备
remotePath=oneDrive:OCI_Ubuntu
<<executeManually
rclone config create oneDrive onedrive
rclone mkdir ${remotePath}
# 手工同步一次
rclone copy ${bakRootDIR} ${remotePath} --progress --verbose
# 首次双向同步,生成 ~/.cache/rclone/bisync/xxx.path1/2.lst 文件
rclone bisync ${bakRootDIR} ${remotePath} --exclude "/dump/**" --resync --verbose --progress
rclone bisync ${bakRootDIR}/dump/ ${remotePath}/dump/ --resync --verbose --progress
ll ~/.cache/rclone/bisync/
executeManually
bakLogFile "Start rclone bisync"
# 双向同步开始,排除正在更新的日志文件
echo -e "\n======= Upload backup files =======" >>${bakRootDIR}/dump/rclone_${currentMonth}.log
rclone bisync ${bakRootDIR} ${remotePath} --exclude "/dump/**" --recover --verbose --log-file ${bakRootDIR}/dump/rclone_${currentMonth}.log
# 备份文件同步结束
bakLogFile "End backupFiles bisync && Start bakLogFile bisync"
# 同步日志文件
rclone bisync ${bakRootDIR}/dump/ ${remotePath}/dump/ --recover --verbose --log-file /var/log/nginx/rcloneDump_${currentMonth}.log

exit

验证

 sudo sh /root/backups.sh abc

sudo crontab -e

# 每日1点,执行备份任务。
0 1 * * * /usr/bin/sh /root/backups.sh tree

目录结构

$ grep ^adm: /etc/group
adm:x:4:lat
$ sudo tree -dL 3 -ugp /data # -d为只显示目录,-L 2为显示深度,-ugp为显示用户,组,权限,-sh以友好方式显示大小。

结果

[drwxr-xr-x root     root    ]  /data
├── [drwxr-x--- root     adm     ]  OCI_Ubuntu
│&nbsp;&nbsp; ├── [drwxr-x--- root     adm     ]  conf
│&nbsp;&nbsp; ├── [drwxr-x--- root     adm     ]  dump
│&nbsp;&nbsp; └── [drwxr-x--- root     adm     ]  wordPress
├── [drwxrwxr-- pubFiles pubFiles]  downloads
└── [drwxr-xr-x root     root    ]  www
    ├── [drwxr-xr-x root     root    ]  html
    ├── [drwxr-x--- www-data adm     ]  log
    ├── [drwxr-xr-x root     root    ]  nginxCache
        ├── [drwxr-xr-x www-data adm     ]  blog.t725.cn
    └── [drwxr-xr-x www-data adm     ]  wordPress

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注