项目经理
·JF
Linux下的MySQL自动备份shell
字数 14943阅读 2185评论 0赞 1
- #!/bin/bash
-
- # mysql 的备份脚本
- # 备份原理:
- # 1
- # 使用列举出所有的库;
- # 2
- # 使用每个库,列举出每张表,除了指定忽略的库;
- # 3
- # 使用mysqldump 导出每一张表到文件:主机名/年月日/库/表.mysqldump.sql
- # 4
- # 验证每张表的sql文件是否包含完成标志;
- # 5
- # 压缩每个sql文件并删除本sql文件
- # 6
- # 强制删除超过x天的备份文件夹全部文件
- # 7
- # 发送处理日志到指定email
- # 8
- # 请配合同步工具多处服务器备份
-
- # mysql备份配置信息
-
- mysqlBackupUser="backuper"
- # 密码不要包含"号
- mysqlBackupPwd="**#&&&#ddddddd("
- # 日志文件路径/var/log/文件名.log,只记录每次运行的日志
- # 不备份的数据库名称,每个名称使用()号包住,如不备份 abc.d 和 abc.e二个数据库,就拼写成"(abc.d)(abc.e)",名字不区分大小写
- notBackupDatabases="(mysql)(information_schema)(performance_schema)"
- #备份的目录,后面需要加/
- backupRoot="/var/backup/hostname-mysql-data/"
- # 删除存在大于以下天数的备份目录
- deleteRootOutDays=30
- #必须是完整的email地址,因为正面的命令使用到
- smtpUser="qidizi@qq.com"
- #smtp://协议是必须的
- smtpHost="smtp://smtp.qq.com:25"
- #密码不能包含又引号防止shell出错
- smtpPwd="pwd"
- smtpTo="qq@qq.com"
- smtpSubject="主机上的mysql自动备份脚本执行信息"
- # 配置结束行
-
- shName=$(basename $0)
- shLogPath="/var/log/${shName}.log"
-
- ver=$(realpath --version 2>&1)
-
- if [ "$?" -ne "0" ];then
- echo "测试realpath --version的版本时出错,中止,出错信息:${ver}"
- exit 10
- fi
-
- echo -e "$(date "+%Y-%m-%d %R:%S") By $(realpath ${0})n" > $shLogPath
-
- function myExit(){
- exitCode=$1
- ver=$(mailx -V 2>&1)
- appendLog "退出时间:$(date +%Y-%m-%d/%R:%S)"
- appendLog "服务器信息:n$(ifconfig 2>&1)"
-
- if [ "$?" -ne "0" ];then
- appendLog "测试用来发送email的命令mailx时出错,请安装,如centos使用yum install mailx,忽略发送email通知的步骤,出错信息:${ver}"
- else
- #发送email
- mailInfo=$(mailx -v -s "${smtpSubject}" -S from="${smtpUser}" -S smtp-auth="login" -S smtp="${smtpHost}" -S smtp-auth-user="${smtpUser}" -S smtp-auth-password="${smtpPwd}" -S ssl-verify=ignore "${smtpTo}" < $shLogPath 2>&1)
- # 无法附加发送过程的日志给email通知中,所以,只能保存到日志中,如果需要了解email的交互过程,请到日志文件中查看
- appendLog "退出时间到发送email的时间:$(date +%Y-%m-%d/%R:%S)n使用mailx发送emial通知交互如下:nn${mailInfo}"
- fi
-
- exit $exitCode
- }
-
- # 追加日志
- function appendLog(){
- echo -e "${1} n" >> $shLogPath
- }
-
- if [ ! -e "${backupRoot}" ];then
- appendLog "备份根目录 ${backupRoot} 不存在,已创建"
- mkInfo=$(mkdir -p $backupRoot 2>&1)
-
- if [ "$?" -ne "0" ];then
- appendLog "尝试创建备份目录 ${backupRoot}失败:${mkInfo}"
- myExit 1
- fi
-
- elif [ ! -d "${backupRoot}" ];then
- appendLog "备份根目录路径虽然存在,但是它不是目录,中止:${backupRoot}"
- myExit 2
- fi
-
- #今天的备份目录
- todayRoot="${backupRoot}$(date +%Y%m%d%H)/"
-
- if [ ! -e "${todayRoot}" ];then
- mkInfo=$(mkdir $todayRoot 2>&1)
-
- if [ "$?" -ne "0" ];then
- appendLog "尝试创建本轮的备份目录 ${todayRoot} 失败,中止:${mkInfo}"
- myExit 3
- fi
- fi
-
- appendLog "今天的备份目录:${todayRoot}"
- ver=$(mysql --version 2>&1)
-
- if [ "$?" -ne "0" ];then
- appendLog "测试mysql的版本时出错,中止,出错信息:${ver}"
- myExit 4
- fi
-
- ver=$(mysqldump -V 2>&1)
-
- if [ "$?" -ne "0" ];then
- appendLog "测试mysqldump命令出错,请安装,中止,出错信息:${ver}"
- myExit 5
- fi
-
- ver=$(tail --version 2>&1)
-
- if [ "$?" -ne "0" ];then
- appendLog "测试tail命令的版本时出错,中止,出错信息:${ver}"
- myExit 41
- fi
-
- ver=$(tar --version 2>&1)
-
- if [ "$?" -ne "0" ];then
- appendLog "测试tar命令的版本时出错,中止,出错信息:${ver}"
- myExit 42
- fi
-
- databases=$(mysql --host="127.0.0.1" --user="${mysqlBackupUser}" --password="${mysqlBackupPwd}" --execute="show databases;" --silent --skip-column-names --unbuffered 2>&1)
-
- if [ "$?" -ne "0" ]; then
- appendLog "尝试使用配置信息列举mysql的数据库名时出错,中止:${databases}"
- myExit 6
- else
- appendLog "全部的数据库名称列表如下:n ${databases}"
- fi
-
-
- for database in $databases; do
- # 匹配时不区分大小写
- echo $notBackupDatabases|grep -i "(${database})" >/dev/null
-
- # 属于不需要备份的库
- if [ "$?" -eq "0" ];then
- appendLog "数据库 ${database} 被指定不需要备份,跳过"
- continue
- fi
-
- databaseRoot="${todayRoot}${database}/"
-
- if [ ! -e "${databaseRoot}" ];then
- mkInfo=$(mkdir $databaseRoot 2>&1)
-
- if [ "$?" -ne "0" ];then
- appendLog "尝试创建数据库 ${databaseRoot} 的目录失败,中止:${mkInfo}"
- myExit 7
- fi
- fi
-
-
- tables=$(mysql --host="127.0.0.1" --user="${mysqlBackupUser}" --password="${mysqlBackupPwd}" --execute="show tables from `${database}`;" --silent --skip-column-names --unbuffered 2>&1)
-
- if [ "$?" -ne "0" ]; then
- appendLog "尝试使用配置信息列举mysql的数据库 ${database} 表的列表时出错,中止:${tables}"
- myExit 8
- else
- appendLog "${database}数据库表的全部列表如下:n ${tables}"
- fi
-
- for table in $tables; do
- sqlPath="${databaseRoot}${table}.sql"
- timeStart="开始dump时间点: $(date +%Y-%m-%d/%R:%S)"
- dumpInfo=$(mysqldump --host="127.0.0.1" --user="${mysqlBackupUser}" --password="${mysqlBackupPwd}" --dump-date --comments --quote-names --result-file="${sqlPath}" --quick --databases "${database}" --tables "${table}" 2>&1 )
- timeEnd="完成dump时间点: $(date +%Y-%m-%d/%R:%S)"
-
- if [ "$?" -ne "0" ];then
- appendLog "尝试导出数据库 ${database}的表 ${table} 失败,中止:${dumpInfo}"
- myExit 9
- else
- appendLog "导出数据库 ${database}的表 ${table} 到 ${sqlPath} 成功:${dumpInfo}; 耗时: 从 ${timeStart} 至 ${timeEnd}"
-
- tail --lines=10 "${sqlPath}" |grep "-- Dump completed" 2>&1 > /dev/null
-
- if [ "$?" -ne "0" ];then
- appendLog "没有发发现内容中的 'Dump completed' 正常完成标志字符,请检查dump文件${sqlPath},请登录ssh查看此文件是否备份成功"
- else
- appendLog "检测到备份文件内容中的'Dump completed'标志字符,dump文件${sqlPath}应该备份成功了"
- fi
-
- fi
-
- done
-
- done
-
- appendLog "n ------数据库备份全部完成------n"
-
- # 开始压缩,把压缩放到备份结束是防止压缩时间过长,如果出现锁表,会影响网站运行
- sqls=$(ls --almost-all --ignore-backups --indicator-style=slash -1 ${todayRoot}*/*.sql 2>&1)
-
- for path in $sqls; do
- #路径中包含了绝对路径,tar命令还需要改进
- sqlDir=$(dirname $path)
- sql=$(basename $path)
- tarInfo=$(tar --create --remove-files --bzip2 --absolute-names --directory="${sqlDir}" --add-file="${sql}" --file="${path}.tar.bz2")
-
- if [ "$?" -ne "0" ];then
- appendLog "压缩并删除${path}文件时出错:n${tarInfo}"
- else
- appendLog "已压缩并删除${path}"
- fi
- done
-
- appendLog "------完成压缩操作-----"
- #开始清理大于x天的备份
-
- daysDir=$(ls --almost-all --ignore-backups --indicator-style=slash -1 "${backupRoot}" 2>&1)
-
- for bkDir in $daysDir;do
- bkDir="${backupRoot}${bkDir}"
-
- if [ ! -d "${bkDir}" ];then
- appendLog "准备删除过期的备份操作时,因为${bkDir}不是一个目录,跳过"
- continue
- fi
-
- dirName=$(basename $bkDir)
- #test
- echo $dirName | grep -P "^d{10}$" 2>&1 >/dev/null
-
- if [ "$?" -ne "0" ];then
- appendLog "准备删除过期备份目录时,检测到待删除目录名不是10位数字,跳过:${bkDir}"
- continue
- fi
-
- outDay=$(date --date="-${deleteRootOutDays}day" "+%Y%m%d00")
-
- #如果文件时间小于这个过期时间那么就强制删除整个目录
- if [ "${dirName}" -lt "${outDay}" ];then
- rmInfo=$(rm --force --preserve-root --recursive "${bkDir}" 2>&1)
- appendLog "发现一个过期备份目录 ${bkDir},已经超过 ${deleteRootOutDays} 天,也就是小于${outDay}就会被删除 ,被强制删除状态(0为成功):${?} ${rmInfo};"
- fi
-
- done
-
- appendLog "------完成清理过期备份文件夹操作----"
- appendLog "空间使用情况如下:n $(df -h)"
- appendLog "当前备份文件占用空间情况:n $(du -hs ${todayRoot})"
- myExit 0
如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!
赞1
添加新评论0 条评论