001 | #!/bin/sh | |
002 | LANG=C |
003 | date=$(date -d "today" +"%Y-%m-%d %H:%M:%S") | |
004 |
|
005 | #---------------配置信息(开始)--------------- | |
006 | #类型:主机设为master,备机设为slave |
007 | type="master" | |
008 |
|
009 | #主机、备机切换日志路径 | |
010 | logfile="/var/log/failover.log" |
011 |
| |
012 | #MySQL可执行文件地址,例如/usr/local/mysql/bin/mysql;MySQL用户名;密码;端口 |
013 | mysql_bin="/usr/local/webserver/mysql/bin/mysql" | |
014 | mysql_username="root" |
015 | mysql_password="123456" | |
016 | mysql_port="3306" |
017 |
| |
018 | #内网网关 |
019 | gateway_eth0="192.168.146.1" | |
020 |
|
021 | #主机内网真实IP | |
022 | rip_eth0_master="192.168.146.213" |
023 |
| |
024 | #备机内网真实IP |
025 | rip_eth0_slave="192.168.146.215" | |
026 |
|
027 | #主机、备机内网共用的虚拟IP | |
028 | vip_eth0_share="192.168.113.214" |
029 |
|
030 |
|
031 | #外网网关 | |
032 | gateway_eth1="72.249.146.193" |
033 |
| |
034 | #主机外网真实IP |
035 | rip_eth1_master="72.249.146.213" | |
036 |
|
037 | #备机外网真实IP | |
038 | rip_eth1_slave="72.249.146.215" |
039 |
| |
040 | #主机、备机外网共用的虚拟IP |
041 | vip_eth1_share="72.249.146.214" | |
042 | #---------------配置信息(结束)--------------- |
043 |
| |
044 | #绑定内、外网虚拟IP |
045 | function_bind_vip() | |
046 | { |
047 | /sbin/ifconfig eth0:vip ${vip_eth0_share} broadcast ${vip_eth0_share} netmask 255.255.255.255 up | |
048 | /sbin/route add -host ${vip_eth0_share} dev eth0:vip |
049 | /sbin/ifconfig eth1:vip ${vip_eth1_share} broadcast ${vip_eth1_share} netmask 255.255.255.255 up | |
050 | /sbin/route add -host ${vip_eth1_share} dev eth1:vip |
051 | /usr/local/webserver/php/sbin/php-fpm reload | |
052 | kill -USR1 `cat /usr/local/webserver/nginx/logs/nginx.pid` |
053 | /sbin/service crond start | |
054 | } |
055 |
| |
056 | #解除内、外网虚拟IP |
057 | function_remove_vip() | |
058 | { |
059 | /sbin/ifconfig eth0:vip ${vip_eth0_share} broadcast ${vip_eth0_share} netmask 255.255.255.255 down |
060 | /sbin/ifconfig eth1:vip ${vip_eth1_share} broadcast ${vip_eth1_share} netmask 255.255.255.255 down |
061 | /sbin/service crond stop | |
062 | } |
063 |
| |
064 | #主机向备机推送文件的函数 |
065 | function_rsync_master_to_slave() | |
066 | { |
067 | /usr/bin/rsync -zrtuog /data0/htdocs/ ${rip_eth0_slave}::data0_htdocs/ > /dev/null 2>&1 |
068 | /usr/bin/rsync -zrtuog /usr/local/webserver/php/etc/ ${rip_eth0_slave}::php_etc/ > /dev/null 2>&1 |
069 | /usr/bin/rsync -zrtuog /usr/local/webserver/nginx/conf/ ${rip_eth0_slave}::nginx_conf/ > /dev/null 2>&1 | |
070 | } |
071 |
| |
072 | #备机向主机推送文件的函数 |
073 | function_rsync_slave_to_master() | |
074 | { |
075 | /usr/bin/rsync -zrtuog /data0/htdocs/ ${rip_eth0_master}::data0_htdocs/ > /dev/null 2>&1 |
076 | /usr/bin/rsync -zrtuog /usr/local/webserver/php/etc/ ${rip_eth0_master}::php_etc/ > /dev/null 2>&1 |
077 | /usr/bin/rsync -zrtuog /usr/local/webserver/nginx/conf/ ${rip_eth0_master}::nginx_conf/ > /dev/null 2>&1 | |
078 | } |
079 |
| |
080 | #虚拟IP ARPing |
081 | function_vip_arping() | |
082 | { |
083 | /sbin/arping -I eth0 -c 3 -s ${vip_eth0_share} ${gateway_eth0} > /dev/null 2>&1 |
084 | /sbin/arping -I eth1 -c 3 -s ${vip_eth1_share} ${gateway_eth1} > /dev/null 2>&1 |
085 | } |
086 |
|
087 | while true | |
088 | do |
089 | #用HTTP协议检查虚拟IP | |
090 | if(curl -m 30 -G http://${vip_eth1_share}/ > /dev/null 2>&1) && (${mysql_bin} -u"${mysql_username}" -p"${mysql_password}" -P"${mysql_port}" -h"${vip_eth0_share}" -e"show slave status\G" > /dev/null 2>&1) |
091 | then | |
092 | #取得与内网VIP绑定的服务器内网IP |
093 | eth0_active_server=$(${mysql_bin} -u"${mysql_username}" -p"${mysql_password}" -P"${mysql_port}" -h"${vip_eth0_share}"-e"show slave status\G" | grep "Master_Host" | awk -F ': ' '{printf $2}') | ||
094 |
| ||
095 | #如果内网VIP=主机内网IP(主机MySQL中的Master_Host显示的是备机的域名或IP),且本机为主机 | |
096 | if [ "${eth0_active_server}" = "${rip_eth0_slave}" ] && [ "${type}" = "master" ] | |
097 | then | |
098 | function_rsync_master_to_slave |
099 | function_vip_arping | |
100 | #如果内网VIP=备机内网IP(备机MySQL中的Master_Host显示的是主机的域名或IP) |
101 | elif [ "${eth0_active_server}" = "${rip_eth0_master}" ] | |
102 | then |
103 | if(curl -m 30 -G http://${rip_eth1_master}/ > /dev/null 2>&1) && (${mysql_bin} -u"${mysql_username}" -p"${mysql_password}" -P"${mysql_port}" -h"${rip_eth0_master}" -e"show slave status\G" | grep "Seconds_Behind_Master: 0" > /dev/null 2>&1) | |
104 | then |
105 | #如果主机能够访问,数据库同步无延迟,且本机就是主机,那么由本机绑定虚拟IP | |
106 | if [ "${type}" = "master" ] |
107 | then | |
108 | #如果本机为主机 |
109 | function_bind_vip | |
110 | function_vip_arping |
111 | echo "${date} 主机已绑定虚拟IP!(Type:1)" >> ${logfile} | |
112 | else |
113 | #如果本机为备机 | |
114 | function_remove_vip |
115 | echo "${date} 备机已去除虚拟IP!(Type:2)" >> ${logfile} | |
116 | fi |
117 | else | |
118 | if [ "${type}" = "slave" ] |
119 | then | |
120 | #如果本机为备机 |
121 | function_rsync_slave_to_master | |
122 | function_vip_arping |
123 | fi | |
124 | fi |
125 | fi | |
126 | else |
127 | #虚拟IP无法访问时,判断主机能否访问 | |
128 | if(curl -m 30 -G http://${rip_eth1_master}/ > /dev/null 2>&1) && (${mysql_bin} -u"${mysql_username}" -p"${mysql_password}" -P"${mysql_port}" -h"${rip_eth0_master}" -e"show slave status\G" > /dev/null 2>&1) |
129 | then | |
130 | #如果主机能够访问,且本机就是主机,那么由本机绑定虚拟IP |
131 | if [ "${type}" = "master" ] | |
132 | then |
133 | function_bind_vip | |
134 | function_vip_arping |
135 | echo "${date} 主机已绑定虚拟IP!(Type:3)" >> ${logfile} | |
136 | else |
137 | function_remove_vip | |
138 | echo "${date} 备机已去除虚拟IP!(Type:4)" >> ${logfile} |
139 | fi | |
140 | elif (curl -m 30 -G http://${rip_eth1_slave}/ > /dev/null 2>&1) && (${mysql_bin} -u"${mysql_username}" -p"${mysql_password}" -P"${mysql_port}" -h"${rip_eth0_slave}" -e"show slave status\G" > /dev/null 2>&1) |
141 | then | |
142 | #如果主机不能访问而备机能够访问,且本机就是备机,那么由备机绑定虚拟IP |
143 | if [ "${type}" = "slave" ] | |
144 | then |
145 | function_bind_vip | |
146 | function_vip_arping |
147 | echo "${date} 备机已绑定虚拟IP!(Type:5)" >> ${logfile} | |
148 | else |
149 | function_remove_vip | |
150 | echo "${date} 主机已去除虚拟IP!(Type:6)" >> ${logfile} |
151 | fi | |
152 | else |
153 | echo "${date} 主机、备机全部无法访问!(Type:7)" >> ${logfile} | |
154 | fi |
155 | fi | |
156 | #每次循环暂停20秒(即间隔20秒检测一次) |
157 | sleep 20 | |
158 | done |