用shell脚本实现mysql自动主从的配置

本人小白,说错还请多多见谅。

目录

登陆服务器

安装mysql,开启二进制日志

设置变量,数据库密码

mysql语句脚本中执行方式

将接受授权命令写入文件并发送

远程cat问题

远程执行的接受授权脚本

其他可以实现的功能


登陆服务器

首先明确,免密登陆是必要的。虽然有不适用免密登陆的方法,但这些方法都会泄露密码信息。直接使用ansible对一个小实验又没必要。因此这里使用免密登陆。

安装mysql,开启二进制日志

要实现主从同步,安装是必不可少的。由于我用的系统是centos7,用的是mariadb,所以我这样安装。
 

. /mysql-gaokeyong/kaiqierjinzhirizhi
#加载开启binlog日志的函数
yum -y install mariadb  mariadb-server
#安装mysql
kaiqierjinzhirizhi
#执行开启binlog日志
systemctl restart mariadb
#重启mysql

 以上是脚本代码的一部分,用来安装主库的mysql。其中,kaiqierjinzhirizhi(开启二进制日志)是我自己定义的一个函数,在另一个脚本中被调用。代码如下:

#/bin/bash

#这个函数是为了判断binlog日志有没有开启,没有开启就开启一下
function kaiqierjinzhirizhi
{
  if  ! grep -Eqw "server-id|log-bin=mariadb-bin" /etc/my.cnf;then
     echo "需要写入"
     sed  -i  '4i server-id=1' /etc/my.cnf
     sed -i   '5i log-bin=mariadb-bin' /etc/my.cnf
  else
     echo "不需要写入"
  fi
}

这里grep -qw有一个判断功能,有内容返回0,没内容返回1.这里用!取反。所以,无值返回0,然后执行sed写入/etc/my.cnf的操作。这里的-E为了让-qw支持|的分支匹配。

在实际情况中,如果没有-E,在有分支匹配的情况下,会默认结果为零,然后你每次测试的时候都会sed写入,最后重复多条,汗流浃背了!

设置变量,数据库密码

在安装完mysql之后,需要定义一下主库的环境变量,设置主库密码,定义从库环境变量,设置从库密码。

MASTER_HOST="192.168.2.129"
MASTER_PORT=3306
MASTER_USER="root"
MASTER_PASSWORD="MTIzNDU2Cg=="
MASTER_MYSQL_PASSWORD="1234"

mysqladmin -u $MASTER_USER password $MASTER_MYSQL_PASSWORD
#设置主mysql的密码

SLAVE1_HOST="192.168.2.130"
SLAVE1_PORT="3306"
SLAVE1_USER="root"
SLAVE1_PASSWORD="MTIzNDU2Cg=="
SLAVE1_MYSQL_PASSWORD="1234"
rm -rf /mysql-gaokeyong/bianliang
#删除要发送到从的变量信息,开始新一次变量发送
ssh $SLAVE1_USER@$SLAVE1_HOST " rm -rf /root/binaliang"
#删除从服务器的接收授权变量文件
scp /mysql-gaokeyong/yuancheng-kaiqierjinzhirizhi  $SLAVE1_USER@$SLAVE1_HOST:/usr/bin/
#发送写入server-id函数的命令到从服务器
ssh $SLAVE1_USER@$SLAVE1_HOST "yum -y install mariadb mariadb-server;\
yuancheng-kaiqierjinzhirizhi;systemctl start mariadb;mysqladmin -u $SLAVE1_USER password $SLAVE1_MYSQL_PASSWORD"
#从服务安装mysql,执行写入server-id的命令yuancheng-kaiqierjinzhirizhi.重启mysql设置mysql的密码

除此之外,上面还有一个变量信息的发送。

rm -rf /mysql-gaokeyong/bianliang
#删除要发送到从的变量信息,开始新一次变量发送
ssh $SLAVE1_USER@$SLAVE1_HOST " rm -rf /root/binaliang"
#删除从服务器的接收授权变量文件
scp /mysql-gaokeyong/yuancheng-kaiqierjinzhirizhi  $SLAVE1_USER@$SLAVE1_HOST:/usr/bin/

因为从库需要进行授权,授权又要变量,变量无法在新的shell中存在,所以需要远程发送,一次次构建实在是太麻烦了。

yuancheng-kaiqierjinzhirizhi (远程开启二进制日志)。这个文件的作用是在远程执行开启server-id的操作,是为从库设定的。

#/bin/bash

#这个脚本是远程写入server-id的脚本。
function kaiqierjinzhirizhi
{
  if ! grep -Eqw "server-id" /etc/my.cnf ;then
     echo "需要写入"
     sed  -i  '4i server-id=2' /etc/my.cnf
  else
     echo "不需要写入"
  fi
}
kaiqierjinzhirizhi

这里其实如果有多台从库,server-id应该改成一个变量用位置参数变量调入,然后在一个专门的文件里修改。但是我只是简单的小实验,不用那么麻烦,有兴趣的可以尝试。

接下来在主库对从库进行授权设置。

然后就要考虑,mysql在脚本中,怎么通过非交互的方式进行授权。

mysql语句脚本中执行方式

这里有四种方式

第一种 :直接使用 mysql -e “命令”  进行授权。这样干的麻烦是命令太长了不太美观。

第二种:使用sql构造语句。

SQL_GRANT="GRANT REPLICATION SLAVE, SELECT ON *.* TO 'slave'@'%s' IDENTIFIED BY '%s';"
GRANT_CMD=$(printf "$SQL_GRANT" "$SLAVE1_HOST" "$SLAVE1_MYSQL_PASSWORD")
SQL_STATUS="SHOW MASTER STATUS;"
#主服务器构造sql语句,方遍后面输入

mysql -u "$MASTER_USER" -p"$MASTER_MYSQL_PASSWORD" -e "$GRANT_CMD"
#将构造好的授权语句在mysql中执行

这样的好处是最后执行的命令不长,而且方便修改变量。至于缺点,这个远程执行才会体现出来。

这里其实是在第一句中将变量写成%s,在第二句中将第一句当作变量输出,依次按照变量顺序输入变量。最后把第二局当作变量,给mysql执行。

第三种,使用管道符过滤,将echo的输出传输到后面的mysql

echo “命令” | mysql 

这样做和以上一样也有一个巨大的缺点,再下面的内容会指出

第四种,将mysql的命令直接写入文件,用<指向mysql

     mysql < 文件

在主库授权时,使用了构造语句的方式(一开始不知道使用文件输入的方式)

SQL_GRANT="GRANT REPLICATION SLAVE, SELECT ON *.* TO 'slave'@'%s' IDENTIFIED BY '%s';"
GRANT_CMD=$(printf "$SQL_GRANT" "$SLAVE1_HOST" "$SLAVE1_MYSQL_PASSWORD")
SQL_STATUS="SHOW MASTER STATUS;"
#主服务器构造sql语句,方遍后面输入

mysql -u "$MASTER_USER" -p"$MASTER_MYSQL_PASSWORD" -e "$GRANT_CMD"
#将构造好的授权语句在mysql中执行

 接下来需要让从库接受授权,接收授权之前先要提取二进制日志文件名和偏移量。

将接受授权命令写入文件并发送

BINLOG=$(mysql -u "$MASTER_USER" -p"$MASTER_MYSQL_PASSWORD" -e "$SQL_STATUS" | awk 'NR>1{ print $1}')
#提取binlog日志名
POSITION=$(mysql -u "$MASTER_USER" -p"$MASTER_MYSQL_PASSWORD" -e "$SQL_STATUS"| awk 'NR>1{ print $2}')
#提取当前偏移量

touch /mysql-gaokeyong/bianliang
#创建确认授权变量文件
echo -e  "CHANGE MASTER TO MASTER_HOST='$MASTER_HOST'\
,MASTER_PORT=3306,\
MASTER_USER='slave',\
MASTER_PASSWORD='$MASTER_MYSQL_PASSWORD',\
MASTER_LOG_FILE='$BINLOG'\
,MASTER_LOG_POS=$POSITION;" >> /mysql-gaokeyong/bianliang
#将确认授权,写入变量文件。

以上就是mysql的偏移量和二进制日志文件名提取作为变量,然后写入文件。

ssh $SLAVE1_USER@$SLAVE1_HOST "mkdir /root/mysqlbianliang/"
#创建变量文件所在目录
scp /mysql-gaokeyong/bianliang  $SLAVE1_USER@$SLAVE1_HOST:/root/mysqlbianliang/
#将变量文件发送给远程服务器
ssh $SLAVE1_USER@$SLAVE1_HOST " chmod 777  /root/mysqlbinaliang/bianliang"
#为变量文件设置权限

这个是将变量文件发送到从服务器,方便被调用。

远程cat问题

现象

在命令行远程可以cat文件内容,同样的命令但在脚本就不行。(有兴趣的可以自己尝试一下)

这个有什么弊端?

如果不能cat,那么awk、grep同样不能使用,请问你怎么提取变量?

然后我去上网查了一下为什么在脚本中ssh  用户@ip   “命令”   无法使用cat命令?

结果网上的答案是,cat以及其他查看文件内容的命令,其实需要一个终端,而shell脚本的bash环境其实不能提供这个终端,所以无法cat。

解决这个问题的方法也很简单,用-t生成一个伪终端。

ssh -tt $SLAVE1_USER@$SLAVE1_HOST <yuanchengjiaobeng.sh
#-t开启一个伪终端,在伪终端通过传入的脚本设置从服务器的mysql主从配置

这里的-tt表示生成一个更加好的伪终端,后面的脚本是在这个伪终端中执行的。因为一开始我不用脚本输入的方式依旧不能cat,具体原因我不太清楚,不过用脚本输入就可以执行了。

远程执行的接受授权脚本

#!/bin/bash

cd  /root/
#确认存放变量文件的目录
rm -rf change_master.sql
#删除上次的变量文件
MASTER_HOST="192.168.2.129"
MASTER_PORT=3306
MASTER_USER="root"
MASTER_PASSWORD="MTIzNDU2Cg=="
MASTER_MYSQL_PASSWORD="MTIzNAo="

SLAVE1_HOST="192.168.2.130"
SLAVE1_PORT="3306"
SLAVE1_USER="root"
SLAVE1_PASSWORD="MTIzNDU2Cg=="
SLAVE1_MYSQL_PASSWORD="1234"





cp  /root/mysqlbianliang/bianliang  /root/change_master.sql
#将接收授权变量传递给授权文件

mysql -u $SLAVE1_USER -p$SLAVE1_MYSQL_PASSWORD < /root/change_master.sql
#确认授权的过程
echo "start slave;" |mysql -u$SLAVE1_USER -p$SLAVE1_MYSQL_PASSWORD
#开启主从
mysql -u$SLAVE1_USER -p$SLAVE1_MYSQL_PASSWORD -e "show slave status\G;"
#查看主从
exit
#退出终端

我这里懒得讲变量写入文件然后发送提取了,不过使用  ssh 用户@ip <脚本   的方式已经可以在这个脚本中实现awk提取了。有兴趣的可以试一下。

这里我重点讲一下为什么要文件传入命令给mysql的问题。

刚开始我使用awk提取变量,然后用sql构造语句的方式执行,最大的问题就是太长了,容易错。

什么地方多了个“立马报错,多次调用还很难找到。除此之外,我发现伪终端的行长度,是有限的,超出长度的变量会被夹断报错。

如图所示,将接收授权过程用直接写入的方式。看看脚本执行主从会不会报错。

CHANGE=$(awk 'NR==1' /root/mysqlbianliang/bianliang )


cp  /root/mysqlbianliang/bianliang  /root/change_master.sql
#将接收授权变量传递给授权文件

#mysql -u $SLAVE1_USER -p$SLAVE1_MYSQL_PASSWORD < /root/change_master.sql 
#确认授权的过程
mysql -u $SLAVE1_USER -p$SLAVE1_MYSQL_PASSWORD -e "$CHANGE"

 没报错,太尴尬了,不过,太长的命令确实容器报错,所以我最终使用了文件传入的方式。

其他可以实现的功能

其实还可以搞个keepalive+lvs实现高可用,可以自己去实现。另外使用函数调用和位置参数变量传入的方式,实现修改配置和脚本的解耦也是可以的,建议有兴趣的尝试,散会。

  • 52
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值