Qingquan-Li / blog

My Blog
https://Qingquan-Li.github.io/blog/
132 stars 16 forks source link

使用 cron 定时备份 MySQL 数据库(使用 Ubuntu 系统) #153

Open Qingquan-Li opened 4 years ago

Qingquan-Li commented 4 years ago

环境:


一、自动备份MySQL数据库的 .sh 脚本

注意:运行此脚本的系统(这里是 Ubuntu )上需要先安装好 MySQL,否则将会报错:mysql: command not found 。参考:FatliTalk - Ubuntu 安装 MySQL 5.7

mysql_user="root" #需要备份的MySQL的用户名,这里用户名为root
mysql_password="password" #需要备份的MySQL用户密码
mysql_host="IP地址" #在运行MySQL的服务器进行本地备份,IP地址填localhost";在另一台服务器对MySQL进行备份,则填写运行MySQL的服务器的IP地址
mysql_port="3306"
mysql_charset="utf8" #MySQL编码
backup_db_arr=("db01") #要备份的数据库名称,多个用空格分开隔开 如("db01" "db02" "db03")
backup_location=~/db01_backup #备份数据存放位置,末尾请不要带"/",如果没有db01_backup这个文件夹,程序会自动创建文件夹
expire_backup_delete="ON" #是否开启过期备份删除,ON为开启,OFF为关闭
expire_days=7 #过期时间天数。默认为三天,此项只有在expire_backup_delete开启时有效

# 本行开始以下不需要修改
backup_time=`date +%Y%m%d%H%M` #定义备份详细时间
backup_Ymd=`date +%Y-%m-%d` #定义备份目录中的年月日时间
backup_7ago=`date -d '7 days ago' +%Y-%m-%d` #7天之前的日期
backup_dir=$backup_location/$backup_Ymd #备份文件夹全路径
welcome_msg="Welcome to use MySQL backup tools!" #欢迎语

# 判断MYSQL是否启动,mysql没有启动则备份退出
# 注意:运行此脚本的系统上需要先安装好MySQL,否则将会报错:mysql: command not found
mysql_ps=`ps -ef |grep mysql |wc -l`
mysql_listen=`netstat -an |grep LISTEN |grep $mysql_port|wc -l`
if [ [$mysql_ps == 0] -o [$mysql_listen == 0] ]; then
echo "ERROR:MySQL is not running! backup stop!"
exit
else
echo $welcome_msg
fi

# 连接到mysql数据库,无法连接则备份退出
mysql -h$mysql_host -P$mysql_port -u$mysql_user -p$mysql_password <<end
use mysql;
select host,user from user where user='root' and host='localhost';
exit
end

flag=`echo $?`
if [ $flag != "0" ]; then
echo "ERROR:Can't connect mysql server! backup stop!"
exit
else
echo "MySQL connect ok! Please wait......"
# 判断有没有定义备份的数据库,如果定义则开始备份,否则退出备份
if [ "$backup_db_arr" != "" ];then
#dbnames=$(cut -d ',' -f1-5 $backup_database)
#echo "arr is (${backup_db_arr[@]})"
for dbname in ${backup_db_arr[@]}
do
echo "database $dbname backup start..."
`mkdir -p $backup_dir`
`mysqldump -h$mysql_host -P$mysql_port -u$mysql_user -p$mysql_password $dbname --default-character-set=$mysql_charset | gzip > $backup_dir/$dbname-$backup_time.sql.gz`
flag=`echo $?`
if [ $flag == "0" ];then
echo "database $dbname success backup to $backup_dir/$dbname-$backup_time.sql.gz"
else
echo "database $dbname backup fail!"
fi

done
else
echo "ERROR:No database to backup! backup stop"
exit
fi
# 如果开启了删除过期备份,则进行删除操作
if [ "$expire_backup_delete" == "ON" -a "$backup_location" != "" ];then
`find $backup_location/ -type d -mtime +$expire_days | xargs rm -rf`
echo "Expired backup data delete complete!"
# 移动过期备份到 ~/delete 目录下,而不是直接删除:
# `find $backup_location/ -type d -mtime +$expire_days | xargs -I {} mv {} ~/delete`
# echo "Expired backup data move to delete directory complete!"
fi
echo "All database backup success! Thank you!"
exit
fi


二、编写 crontab 文件定时执行脚本

参考:

【crontab 文件格式】时间+动作:

# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12)
# │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday;
# │ │ │ │ │                                       7 is also Sunday on some systems)
# │ │ │ │ │
# │ │ │ │ │
# * * * * * command to execute

【实例】编写 crontab 脚本文件,定时执行 MySQL 备份脚本:

$ crontab -e # 编辑当前用户的crontab文件
# 进入 vim 进行编辑,例如每天凌晨 02:00 执行 ~/db_backup 目录下
# 的 mysqlbackup.sh 脚本:00 02 * * * cd ~/db_backup && ./mysqlbackup.sh

$ crontab -l # 列出当前用户编辑的crontab文件的内容
00 02 * * * cd ~/db_backup && ./mysqlbackup.sh

$ crontab -r # 从/var/spool/cron目录中删除某个用户的crontab文件,如果不指定用户,则默认删除当前用户的crontab文件(上面 crontab -e 创建的 crontab 脚本文件)。


三、Ubuntu下cron定时任务脚本不被执行的问题

参考:

1. 测试-找出问题:

$ crontab -l
* * * * * echo "Hello"
# tail 命令:显示指定文件的末尾10行,control+C退出(这里使用的是本地虚拟机上的Ubuntu)
$ tail /var/log/syslog
May  8 02:26:01 fatli-vm-ubuntu CRON[63924]: (fatli) CMD (echo "Hello")
May  8 02:26:01 fatli-vm-ubuntu CRON[63923]: (CRON) info (No MTA installed, discarding output)
May  8 02:27:01 fatli-vm-ubuntu CRON[63928]: (fatli) CMD (echo "Hello")
May  8 02:27:01 fatli-vm-ubuntu CRON[63927]: (CRON) info (No MTA installed, discarding output)
May  8 02:28:01 fatli-vm-ubuntu CRON[63933]: (fatli) CMD (echo "Hello")
May  8 02:28:01 fatli-vm-ubuntu CRON[63932]: (CRON) info (No MTA installed, discarding output)
May  8 02:29:01 fatli-vm-ubuntu CRON[63937]: (fatli) CMD (echo "Hello")
May  8 02:29:01 fatli-vm-ubuntu CRON[63936]: (CRON) info (No MTA installed, discarding output)
May  8 02:30:01 fatli-vm-ubuntu CRON[63941]: (fatli) CMD (echo "Hello")
May  8 02:30:01 fatli-vm-ubuntu CRON[63940]: (CRON) info (No MTA installed, discarding output)
# 发现原因是:Ubuntu 不同于其他 Linux 发行版,Ubuntu 默认没有安装包含 MTA (Mail Transfer Agent)的邮件服务,导致 cron 不能发送通知(日志)给用户。
$ crontab -e
# 修改crontab脚本文件:* * * * * echo "Hello world!" >> ~/db_backup/cron4test.log
# 再次执行,发现每分钟都会打印一行 Hello world! 到 cron4test.log 文件中,
# 并且执行 `$ tail /var/log/syslog` ,也不见报错 `No MTA installed` 了。

# 注意此处 `>> cron4test.log` 生成的日志文件中,会记录每次执行 crontab 脚本文件的日志输出,每分钟打印一行 "Hello world!";
# 如果改为 `>cron4test.log` 则只记录最近一次执行 crontab 脚本文件的日志输出,也就是永远只有一行 “Hello world!" 。

2. 解决方案:修改 crontab 脚本文件:

$ crontab -e
# 脚本由:00 02 * * * cd ~/db_backup && ./mysqlbackup.sh
# 修改为:00 02 * * * cd ~/db_backup && ./mysqlbackup.sh >> cron4mysqlbackup.log
# 把日志记录在 cron4mysqlbackup.log 中而不是通过邮件发送;或者忽略其日志记录:
# 修改为:00 02 * * * cd ~/db_backup && ./mysqlbackup.sh >/dev/null 2>&1
# /dev/null 2>&1 作用参考:linuxtools-rst.readthedocs.io/zh_CN/latest/tool/crontab.html#id22
# /dev/null 参考:zh.wikipedia.org/wiki//dev/null
# 2>&1 的作用参考:stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean

重启一下 cron 服务(新创建的 cron job,不会马上执行,要过1分钟左右才执行):

$ sudo /etc/init.d/cron restart