| 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 | |
本文介绍了一个双机热备系统中实现虚拟IP自动切换的脚本,包括配置参数、绑定及解除虚拟IP的方法、文件同步过程及健康检查机制。
284

被折叠的 条评论
为什么被折叠?



