asd456
作者asd456·2015-05-07 17:56
项目经理·JF

Linux下的MySQL自动备份shell

字数 14943阅读 2185评论 0赞 1
  1. #!/bin/bash  
  2.   
  3. # mysql 的备份脚本  
  4. # 备份原理:  
  5. # 1  
  6. #   使用列举出所有的库;  
  7. # 2  
  8. #   使用每个库,列举出每张表,除了指定忽略的库;  
  9. # 3  
  10. #   使用mysqldump 导出每一张表到文件:主机名/年月日/库/表.mysqldump.sql  
  11. # 4  
  12. #   验证每张表的sql文件是否包含完成标志;  
  13. # 5  
  14. #   压缩每个sql文件并删除本sql文件  
  15. # 6  
  16. #   强制删除超过x天的备份文件夹全部文件  
  17. # 7  
  18. #   发送处理日志到指定email  
  19. # 8  
  20. #   请配合同步工具多处服务器备份  
  21.   
  22. # mysql备份配置信息  
  23.   
  24. mysqlBackupUser="backuper"  
  25. # 密码不要包含"号  
  26. mysqlBackupPwd="**#&&&#ddddddd("  
  27. # 日志文件路径/var/log/文件名.log,只记录每次运行的日志  
  28. # 不备份的数据库名称,每个名称使用()号包住,如不备份 abc.d 和 abc.e二个数据库,就拼写成"(abc.d)(abc.e)",名字不区分大小写  
  29. notBackupDatabases="(mysql)(information_schema)(performance_schema)"  
  30. #备份的目录,后面需要加/  
  31. backupRoot="/var/backup/hostname-mysql-data/"  
  32. # 删除存在大于以下天数的备份目录  
  33. deleteRootOutDays=30  
  34. #必须是完整的email地址,因为正面的命令使用到  
  35. smtpUser="qidizi@qq.com"  
  36. #smtp://协议是必须的  
  37. smtpHost="smtp://smtp.qq.com:25"  
  38. #密码不能包含又引号防止shell出错  
  39. smtpPwd="pwd"  
  40. smtpTo="qq@qq.com"  
  41. smtpSubject="主机上的mysql自动备份脚本执行信息"  
  42. # 配置结束行  
  43.   
  44. shName=$(basename $0)  
  45. shLogPath="/var/log/${shName}.log"  
  46.   
  47. ver=$(realpath --version 2>&1)  
  48.   
  49. if [ "$?" -ne "0" ];then  
  50.     echo "测试realpath --version的版本时出错,中止,出错信息:${ver}"  
  51.     exit 10  
  52. fi  
  53.   
  54. echo -e "$(date "+%Y-%m-%d %R:%S") By $(realpath ${0})n" > $shLogPath  
  55.   
  56. function myExit(){  
  57.     exitCode=$1  
  58.     ver=$(mailx -V 2>&1)  
  59.     appendLog "退出时间:$(date +%Y-%m-%d/%R:%S)"  
  60.     appendLog "服务器信息:n$(ifconfig 2>&1)"  
  61.   
  62.     if [ "$?" -ne "0" ];then  
  63.         appendLog "测试用来发送email的命令mailx时出错,请安装,如centos使用yum install mailx,忽略发送email通知的步骤,出错信息:${ver}"  
  64.     else  
  65.         #发送email  
  66.         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)  
  67.         # 无法附加发送过程的日志给email通知中,所以,只能保存到日志中,如果需要了解email的交互过程,请到日志文件中查看  
  68.         appendLog "退出时间到发送email的时间:$(date +%Y-%m-%d/%R:%S)n使用mailx发送emial通知交互如下:nn${mailInfo}"  
  69.     fi  
  70.   
  71.     exit $exitCode  
  72. }  
  73.   
  74. # 追加日志  
  75. function appendLog(){  
  76.     echo -e "${1} n" >> $shLogPath  
  77. }  
  78.   
  79. if [ ! -e "${backupRoot}" ];then  
  80.     appendLog "备份根目录 ${backupRoot} 不存在,已创建"  
  81.     mkInfo=$(mkdir -p $backupRoot 2>&1)  
  82.   
  83.     if [ "$?" -ne "0" ];then  
  84.         appendLog "尝试创建备份目录 ${backupRoot}失败:${mkInfo}"  
  85.         myExit 1  
  86.     fi  
  87.   
  88. elif [ ! -d "${backupRoot}" ];then  
  89.     appendLog "备份根目录路径虽然存在,但是它不是目录,中止:${backupRoot}"  
  90.     myExit 2  
  91. fi  
  92.   
  93. #今天的备份目录  
  94. todayRoot="${backupRoot}$(date +%Y%m%d%H)/"  
  95.   
  96. if [ ! -e "${todayRoot}" ];then  
  97.     mkInfo=$(mkdir $todayRoot 2>&1)  
  98.   
  99.     if [ "$?" -ne "0" ];then  
  100.         appendLog "尝试创建本轮的备份目录 ${todayRoot} 失败,中止:${mkInfo}"  
  101.         myExit 3  
  102.     fi  
  103. fi  
  104.   
  105. appendLog "今天的备份目录:${todayRoot}"  
  106. ver=$(mysql --version 2>&1)  
  107.   
  108. if [ "$?" -ne "0" ];then  
  109.     appendLog "测试mysql的版本时出错,中止,出错信息:${ver}"  
  110.     myExit 4  
  111. fi  
  112.   
  113. ver=$(mysqldump -V 2>&1)  
  114.   
  115. if [ "$?" -ne "0" ];then  
  116.     appendLog "测试mysqldump命令出错,请安装,中止,出错信息:${ver}"  
  117.     myExit 5  
  118. fi  
  119.   
  120. ver=$(tail --version 2>&1)  
  121.   
  122. if [ "$?" -ne "0" ];then  
  123.     appendLog "测试tail命令的版本时出错,中止,出错信息:${ver}"  
  124.     myExit 41  
  125. fi  
  126.   
  127. ver=$(tar  --version 2>&1)  
  128.   
  129. if [ "$?" -ne "0" ];then  
  130.     appendLog "测试tar命令的版本时出错,中止,出错信息:${ver}"  
  131.     myExit 42  
  132. fi  
  133.   
  134. databases=$(mysql --host="127.0.0.1" --user="${mysqlBackupUser}"  --password="${mysqlBackupPwd}" --execute="show databases;"  --silent --skip-column-names --unbuffered 2>&1)  
  135.   
  136. if [ "$?" -ne "0" ]; then  
  137.     appendLog "尝试使用配置信息列举mysql的数据库名时出错,中止:${databases}"  
  138.     myExit 6  
  139. else  
  140.     appendLog "全部的数据库名称列表如下:n ${databases}"  
  141. fi  
  142.   
  143.   
  144. for database in $databases; do  
  145.     # 匹配时不区分大小写  
  146.     echo $notBackupDatabases|grep -i "(${database})" >/dev/null  
  147.   
  148.     # 属于不需要备份的库  
  149.     if [ "$?" -eq "0" ];then  
  150.         appendLog "数据库 ${database} 被指定不需要备份,跳过"  
  151.         continue  
  152.     fi  
  153.   
  154.     databaseRoot="${todayRoot}${database}/"  
  155.   
  156.     if [ ! -e "${databaseRoot}" ];then  
  157.         mkInfo=$(mkdir $databaseRoot 2>&1)  
  158.   
  159.         if [ "$?" -ne "0" ];then  
  160.             appendLog "尝试创建数据库 ${databaseRoot} 的目录失败,中止:${mkInfo}"  
  161.             myExit 7  
  162.         fi  
  163.     fi  
  164.   
  165.   
  166.     tables=$(mysql --host="127.0.0.1" --user="${mysqlBackupUser}"  --password="${mysqlBackupPwd}" --execute="show tables from `${database}`;"  --silent --skip-column-names --unbuffered 2>&1)  
  167.   
  168. if [ "$?" -ne "0" ]; then  
  169.     appendLog "尝试使用配置信息列举mysql的数据库 ${database} 表的列表时出错,中止:${tables}"  
  170.     myExit 8  
  171. else  
  172.     appendLog "${database}数据库表的全部列表如下:n ${tables}"  
  173. fi  
  174.   
  175.     for table in $tables; do  
  176.         sqlPath="${databaseRoot}${table}.sql"  
  177.         timeStart="开始dump时间点: $(date +%Y-%m-%d/%R:%S)"  
  178.         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 )  
  179.         timeEnd="完成dump时间点: $(date +%Y-%m-%d/%R:%S)"  
  180.   
  181.         if [ "$?" -ne "0" ];then  
  182.             appendLog "尝试导出数据库 ${database}的表 ${table} 失败,中止:${dumpInfo}"  
  183.             myExit 9  
  184.         else  
  185.             appendLog "导出数据库 ${database}的表 ${table} 到 ${sqlPath} 成功:${dumpInfo}; 耗时: 从 ${timeStart} 至 ${timeEnd}"  
  186.   
  187.             tail --lines=10 "${sqlPath}" |grep "-- Dump completed" 2>&1 > /dev/null  
  188.   
  189.             if [ "$?" -ne "0" ];then  
  190.                 appendLog "没有发发现内容中的 'Dump completed' 正常完成标志字符,请检查dump文件${sqlPath},请登录ssh查看此文件是否备份成功"  
  191.             else  
  192.                 appendLog "检测到备份文件内容中的'Dump completed'标志字符,dump文件${sqlPath}应该备份成功了"  
  193.             fi  
  194.   
  195.         fi  
  196.   
  197.     done  
  198.   
  199. done  
  200.   
  201. appendLog "n ------数据库备份全部完成------n"  
  202.   
  203. # 开始压缩,把压缩放到备份结束是防止压缩时间过长,如果出现锁表,会影响网站运行  
  204. sqls=$(ls --almost-all --ignore-backups --indicator-style=slash -1 ${todayRoot}*/*.sql 2>&1)  
  205.   
  206. for path in $sqls; do  
  207.     #路径中包含了绝对路径,tar命令还需要改进  
  208.     sqlDir=$(dirname $path)  
  209.     sql=$(basename $path)  
  210.     tarInfo=$(tar --create --remove-files --bzip2 --absolute-names --directory="${sqlDir}"   --add-file="${sql}" --file="${path}.tar.bz2")  
  211.   
  212.     if [ "$?" -ne "0" ];then  
  213.         appendLog "压缩并删除${path}文件时出错:n${tarInfo}"  
  214.     else  
  215.         appendLog "已压缩并删除${path}"  
  216.     fi  
  217. done  
  218.   
  219. appendLog "------完成压缩操作-----"  
  220. #开始清理大于x天的备份  
  221.   
  222. daysDir=$(ls --almost-all --ignore-backups --indicator-style=slash -1 "${backupRoot}" 2>&1)  
  223.   
  224. for bkDir in $daysDir;do  
  225.     bkDir="${backupRoot}${bkDir}"  
  226.   
  227.     if [ ! -d "${bkDir}" ];then  
  228.         appendLog "准备删除过期的备份操作时,因为${bkDir}不是一个目录,跳过"  
  229.         continue  
  230.     fi  
  231.   
  232.     dirName=$(basename $bkDir)  
  233.     #test  
  234.     echo $dirName | grep -P "^d{10}$" 2>&1 >/dev/null  
  235.   
  236.     if [ "$?" -ne "0" ];then  
  237.         appendLog "准备删除过期备份目录时,检测到待删除目录名不是10位数字,跳过:${bkDir}"  
  238.         continue  
  239.     fi  
  240.   
  241.     outDay=$(date --date="-${deleteRootOutDays}day" "+%Y%m%d00")  
  242.   
  243.     #如果文件时间小于这个过期时间那么就强制删除整个目录  
  244.     if [ "${dirName}" -lt "${outDay}" ];then  
  245.         rmInfo=$(rm --force --preserve-root --recursive "${bkDir}" 2>&1)  
  246.         appendLog "发现一个过期备份目录 ${bkDir},已经超过 ${deleteRootOutDays} 天,也就是小于${outDay}就会被删除 ,被强制删除状态(0为成功):${?} ${rmInfo};"  
  247.     fi  
  248.   
  249. done  
  250.   
  251. appendLog "------完成清理过期备份文件夹操作----"  
  252. appendLog "空间使用情况如下:n $(df -h)"  
  253. appendLog "当前备份文件占用空间情况:n $(du -hs ${todayRoot})"  
  254. myExit 0

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

1

添加新评论0 条评论

Ctrl+Enter 发表

作者其他文章

相关文章

相关问题

相关资料

X社区推广