想直接看shell脚本的直接拉到最后脚本实战,前面做的是分析和记录。
需求
当存档遇到重灾无法回滚回档的时候,期待读取备份文件的方式手动恢复,要求备份最多保存N天,对于N天前的备份文件进行删除。
实现思路
备份主要就两点需要做到:
- 定时执行备份命令
- 备份的文件需要定时删除
对于第一点采用云服centos系统的crontab
命令实现定时任务,备份则是用zip
命令将存档目录进行压缩。
对于第二点类似日志回滚做法,按照日期命名备份文件,然后针对备份文件名称做日期判断,针对设置过期日,对过期日之前的文件进行删除。
部分命令笔记
crontab
命令
常用就 crontab -e
进行编辑 crontab 的定时任务表达式
crontab -l
查看用户已有定时任务。
但是我想脚本自己去配置定时任务,就可以利用 crontab file
的特点了,就是 crontab 读取文件进行配置,因此我如果需要实现的写法就是:
# crontab表达式
cron_exp="0 */4 * * *"
# 当前脚本所在目录
scriptDir=$(cd $(dirname $0);pwd)
# 读取用户已有配置,conf作为临时文件记录
crontab -l > conf
# 将本次命令加入定时任务配置文件,注意echo ${}这里加了双引号。
echo "${cron_exp}" bash ${scriptDir}/$0 >> conf && crontab conf && echo "定时任务配置成功!" || echo "定时任务配置失败,请检查错误!" && rm -f conf
这样的话,我只需要在脚本中编辑好crontab表达式变量,后面只需要执行当前脚本即可。
zip
压缩命令
之前常用压缩命令都是 tar -zcvf fileName.tar.gz dirName
然后解压就是tar -zxvf filename.tar.gz
但是考虑到存档要取出来,windows用户需要解压使用,所以压缩成zip文件,但是从来没用过zip命令不知道带什么参数,这里正好攻略了下这个命令做个记录。
因为是第一次用,所以很多参数实际效果都要去测试,这里实际常用到就两个参数 zip -qr
参数解释:
- -q 安静的压缩,就是不回显具体压缩了哪些文件
- -r 递归目录,因为是对目录进行压缩而不是单个文件,因此这个参数必须加
之前写遇到很大的一个问题是,我每次压缩都把全路径压缩进去了,即压缩文件解压后,目录层级为:/home/steam/.klei/DonotStarveTogether/Cluster_1
但实际上我只需要压缩Cluster_1这个目录即可。
这里编写就有个小细节,配置变量时候我会定义一个存档目录的变量:
# 存档所在目录
clusterDir="~/.klei/DoNotStarveTogether"
那么压缩的时候就应该是先进入这个目录再进行压缩而不是直接压缩这个全路径下的存档。
完整的 zip 压缩和解压命令:
# 压缩
cd "${clusterDir}" && zip $(date '+%Y%m%d%H%M').zip Cluster_1
# 解压-直接 unzip 文件名 即可
unzip fileName.zip
date 命令
date
命令非常常见,并且经常用到,常见分类应该是:
- 日期格式化输出
- 日期转时间戳(时间戳转日期)
- 日期进行加减运算
具体详解这里不介绍了,只做常用记录。
格式化输出:
# 日期格式化
[steam@VM-12-12-centos tmp]$ date '+%Y-%m-%d %H:%M:%S'
2023-07-05 05:30:28
日期转时间戳(时间戳转日期):
# 日期转时间戳,给定一个日期转,不能直接 date '+%s' 认为是当前时间
[steam@VM-12-12-centos tmp]$ date '+%s' '-d 2023-07-05 05:30:28'
1688506228
# 时间戳转日期-指定日期格式
[steam@VM-12-12-centos tmp]$ date -d @1688506228 '+%Y-%m-%d %H:%M:%S'
2023-07-05 05:30:28
## 时间戳转日期-不指定日期格式
[steam@VM-12-12-centos tmp]$ date -d @1688506228
Wed Jul 5 05:30:28 CST 2023
日期进行加减运算(重点):
# 对当前时间进行加减操作
[steam@VM-12-12-centos tmp]$ date -d '-1 day' '+%Y-%m-%d %H:%M:%S'
2023-07-04 05:40:55
[steam@VM-12-12-centos tmp]$ date -d '-12 hour' '+%Y-%m-%d %H:%M:%S'
2023-07-04 17:41:39
# 对指定日期时间进行加减操作
[steam@VM-12-12-centos tmp]$ date -d '-1 day 2023-07-04 05:40:55' '+%Y-%m-%d %H:%M:%S'
2023-07-03 05:40:55
[steam@VM-12-12-centos tmp]$ date -d '-12 hour 2023-07-04 05:40:55' '+%Y-%m-%d %H:%M:%S'
2023-07-03 17:40:55
# 对 202307050540 这种数字操作加减有个注意点他没法操作带秒的,并且日期和时间要分开写
[steam@VM-12-12-centos tmp]$ date -d '-12 hour 20230704 054055' '+%Y-%m-%d %H:%M:%S'
date: invalid date ‘-12 hour 20230704 054055’
[steam@VM-12-12-centos tmp]$ date -d '-12 hour 20230704054055' '+%Y-%m-%d %H:%M:%S'
date: invalid date ‘-12 hour 20230704054055’
[steam@VM-12-12-centos tmp]$ date -d '-12 hour 202307040540' '+%Y-%m-%d %H:%M:%S'
date: invalid date ‘-12 hour 202307040540’
[steam@VM-12-12-centos tmp]$ date -d '-12 hour 20230704 0540' '+%Y-%m-%d %H:%M:%S'
2023-07-03 17:40:00
最终效果图
备份文件:
日志记录图:
脚本实战
#!/bin/bash
# 定时备份饥荒存档
#
# Date: 2023/06/30
# Author: Tough
# 配置存档
clusterName="Cluster_2"
# 配置过期时间,单位可改: day|hour|minute
expireTime="3 day"
# 脚本设置定时备份时间(当前配置每隔四个小时执行一次备份)
cron_exp="* */4 * * *"
# 备份文件存放的目录
rootDir=$(cd ~/.klei/DoNotStarveTogether && pwd)
backupDir="${rootDir}/backup/${clusterName}"
if [[ ! -d ${backupDir} ]];then
mkdir -p ${backupDir}
fi
# 日志文件
log_file="${rootDir}/backup/backup.log"
targetDir="${rootDir}/${clusterName}"
# 当前脚本所在目录
scriptDir="$(cd $(dirname $0) && pwd)"
#----------------------------------------------------------------------------------#
# 用于打印日志
log(){
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> $log_file
}
# 根据配置不同获取对应的日期命令格式化表达式
func_dateFormate(){
expireType=$(echo ${expireTime}|awk -F' ' '{print $2}')
expireNum=$(echo ${expireTime}|awk -F' ' '{print $1}')
log "获取备份文件日期类型[day|hour|minute]:${expireType}"
case "${expireType}" in
'day')
dateFormateExpression="+%Y%m%d"
;;
'hour')
dateFormateExpression="+%Y%m%d%H"
;;
'minute')
dateFormateExpression="+%Y%m%d%H%M"
;;
*)
log "配置过期时间变量有误,请检查脚本变量:expireTime"
exit 1
;;
esac
}
# 备份方法
func_backup(){
log "------------------------"
log "开始备份存档任务,当前存档:${clusterName}"
log "------------------------"
# 执行备份
destFile="${backupDir}/$(date '+%Y%m%d%H%M')".zip
cd ${rootDir} && zip -qr "${destFile}" "${clusterName}" && log "备份成功,${targetDir} >> ${destFile}" || log "备份失败,请检查错误!"
log "备份存档任务执行结束。"
}
# 删除过期备份文件
func_delete(){
log "-----------------------"
log "开始执行删除过期备份任务,当前配置过期时间 expireTime=${expireTime}"
log "----------------------"
for sourceFile in $(ls ${backupDir})
do
file=${sourceFile%.*}
if [[ -f ${backupDir}/${sourceFile} ]];then
log "当前文件: ${sourceFile}"
today=$(date "+%Y%m%d%H%M")
expireStamp=$(date '+%s' -d "${today:0:8} ${today:8} -${expireNum} ${expireType}")
fileStamp=$(date '+%s' -d "${file:0:8} ${file:8}")
log "过期时间: $(date -d @${expireStamp} '+%Y-%m-%d %H:%M'),文件日期:$(date -d @${fileStamp} '+%Y-%m-%d %H:%M') ==> 计算过期时间戳=${expireStamp},当前文件时间戳=${fileStamp}"
if [[ $fileStamp -lt $expireStamp ]];then
rm -rf ${backupDir}/${sourceFile} && log "删除过期文件 ${backupDir}/${sourceFile} 成功!" || log "删除过期文件 ${backupDir}/${sourceFile} 失败,请检查错误!"
else
log "文件未过期,将保留。"
fi
fi
done
log "删除过期备份任务执行结束。"
}
# 配置定时任务
func_enableCron(){
log "-----------------------"
log "配置定时任务开始"
log "-----------------------"
# 配置定时任务表达式
cronStr="${cron_exp} bash $0 ${clusterName}"
log "生成定时任务 crontab 表达式:${cronStr}"
crontab -l >> conf
log "获取当前用户 $(whoami) 已有定时任务列表:$(cat conf)"
echo "${cronStr}" >> conf && crontab conf && rm -f conf && log "配置定时任务成功" || log "配置定时任务失败,请检查错误!"
log "配置定时任务结束。"
}
# 存在位置参数则为备份和删除任务,不存在则进行配置定时任务
if [[ $# == 0 ]];then
func_enableCron
else
func_dateFormate
func_backup
func_delete
fi