#!/bin/bash ################################################## # EVN # # - SERVER_ID # # - GROUP_REPLICATION # # - GROUP_REPLICATION_LOCAL_ADDRESS # # - GROUP_REPLICATION_GROUP_SEEDS # # - EXTRA_SCRIPTS # # Mount file # # - /etc/my.cnf # # Mount dir # # - LOG_DIR # # - DATA_DIR # # - BINLOG_DIR # ################################################## set -euo pipefail export LANG=en_US.UTF-8 trap Quit EXIT PIDS= GOT_SIGTERM= LOG_DIR='/var/log/mysql' DATA_DIR='/var/lib/mysql' BINLOG_DIR='/var/lib/mysql-bin' SOCK_FILE='/run/mysqld/mysqld.sock' PID_FILE='/run/mysqld/mysqld.pid' INIT_FLAG= GROUP_REPLICATION="${GROUP_REPLICATION:+1}" EXTRA_SCRIPTS="${EXTRA_SCRIPTS:+1}" if [ -n "$GROUP_REPLICATION" ]; then SERVER_ID=${SERVER_ID:?} GROUP_REPILCATION_GROUP_NAME="${GROUP_REPILCATION_GROUP_NAME:-aaaabbbb-7777-8888-9999-ccccddddeeee}" GROUP_REPLICATION_LOCAL_ADDRESS="${GROUP_REPLICATION_LOCAL_ADDRESS}" GROUP_REPLICATION_GROUP_SEEDS="${GROUP_REPLICATION_GROUP_SEEDS}" BOOTSTRAP_GROUP=1 fi function Print { local file=/dev/null [ '-f' = "$1" ] && file=$2 && shift && shift date +"[%F %T] $*" | tee -a $file } function Quit { Print killing mysqld ... mysqladmin shutdown || true while :; do pkill -f mysqld && Print killing mysqld ... || break sleep 1 done Print Container stopped. test -n "$GOT_SIGTERM" } function ProbeSeeds { local all_seeds=" ${GROUP_REPLICATION_GROUP_SEEDS//,/ } " local other_seeds="${all_seeds/ $GROUP_REPLICATION_LOCAL_ADDRESS / }" local seed= seed_return=0 [ "$all_seeds" = "$other_seeds" ] \ && Print Not found local_address in group_seeds! \ && exit 1 Print Probing connection to other seeds ... for seed in $other_seeds; do echo -n "Connecting $seed ... " curl -s --connect-timeout 8 ftp://$seed || seed_return=$? [ 6 = "$seed_return" ] && echo failed to resolve host:"${seed%:*}"! && exit 1 [ 7 = "$seed_return" ] && echo offline. && continue echo online. BOOTSTRAP_GROUP= break done } function Init { rm -f ${SOCK_FILE}* ${PID_FILE} chown -R mysql:mysql $LOG_DIR $BINLOG_DIR $DATA_DIR if [ ! -d "$DATA_DIR/mysql" ]; then Print Writing essential server config to /etc/mysql/my.cnf ... Print Initing mysql db files ... mysqld_pre_systemd INIT_FLAG=1 fi } function InitGroupReplication { if ! grep -i '^group[-_]replication' /etc/my.cnf; then Print Writing advisable group replication config to /etc/my.cnf ... grep -i '^binlog[-_]expire[-_]logs[-_]seconds' /etc/my.cnf \ || echo 'binlog-expire-logs-seconds = 172800' >> /etc/my.cnf echo 'group-replication-consistency = BEFORE_ON_PRIMARY_FAILOVER group-replication-member-expel-timeout = 2 group-replication-unreachable-majority-timeout = 2 group-replication-autorejoin-tries = 0 group-replication-exit-state-action = OFFLINE_MODE ' >> /etc/my.cnf fi if ! grep -i '^group[-_]replication' /etc/mysql/my.cnf; then Print Writing essential group replication config to /etc/mysql/my.cnf ... cat >> /etc/mysql/my.cnf <<-EOF server-id = $SERVER_ID gtid-mode = ON enforce-gtid-consistency = TRUE binlog-format = ROW binlog-checksum = NONE log-bin = /var/lib/mysql-bin/master relay-log = /var/lib/mysql-bin/slave log-slave-updates = TRUE relay-log-recovery = TRUE slave-parallel-type = LOGICAL_CLOCK slave-preserve-commit-order = ON disabled-storage-engines = "MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY" plugin-load-add = "group_replication.so;mysql_clone.so" group-replication-group-name = "$GROUP_REPILCATION_GROUP_NAME" group-replication-local-address = "$GROUP_REPLICATION_LOCAL_ADDRESS" group-replication-group-seeds = "$GROUP_REPLICATION_GROUP_SEEDS" group-replication-bootstrap-group = OFF group-replication-start-on-boot = OFF EOF fi } function ImportInitSql { local sql_file= sql_files= mysql -e "CREATE USER docker@localhost IDENTIFIED BY 'China_19\$(10)!'" mysql -e "GRANT SHUTDOWN ON *.* TO docker@localhost" if sql_files="$(ls $LOG_DIR/init_sql/*.sql 2>/dev/null)"; then Print Importing the sql files ... for sql_file in $sql_files; do Print Importing $sql_file ... mysql < $sql_file done Print Imported all sql files successfully. fi } function StartGroupReplication { if [ -n "$BOOTSTRAP_GROUP" ]; then Print Bootstraping new group replication ... mysql -e " SET GLOBAL group_replication_bootstrap_group=ON; START GROUP_REPLICATION; SET GLOBAL group_replication_bootstrap_group=OFF; " else Print Joining a running group replication ... mysql -e "START GROUP_REPLICATION;" fi } function CreateGroupReplicationChannel { Print Creating user and channel of group replication ... mysql -e "SET SQL_LOG_BIN=0; CREATE USER rpl@'%' IDENTIFIED BY 'Rpl_1234'; GRANT REPLICATION SLAVE ON *.* TO rpl@'%'; GRANT BACKUP_ADMIN ON *.* TO rpl@'%'; FLUSH PRIVILEGES; SET SQL_LOG_BIN=1; CHANGE MASTER TO MASTER_USER='rpl', MASTER_PASSWORD='Rpl_1234' FOR CHANNEL 'group_replication_recovery'; " } function StartExtraScripts { Print Starting extra scripts ... while sleep 2; do for script in $(find $LOG_DIR/extra_scripts/ -type f -executable \ 2>/dev/null || true); do $script & done done & } function StartProc { Print Starting mysql ... mysqld -u mysql & PIDS="$PIDS $!" while sleep 1; do [ -e $SOCK_FILE ] && break || echo -n . [ ! -e /proc/$! ] && echo && Print unexpected error! && exit done echo if [ -n "$INIT_FLAG" ]; then ImportInitSql if [ -n "$GROUP_REPLICATION" ]; then CreateGroupReplicationChannel fi fi if [ -n "$GROUP_REPLICATION" ]; then StartGroupReplication fi if [ -n "$EXTRA_SCRIPTS" ]; then StartExtraScripts fi Print MySQL is ready for connections. } function Main { local pid= [ -n "$GROUP_REPLICATION" ] && ProbeSeeds Init [ -n "$GROUP_REPLICATION" ] && InitGroupReplication StartProc trap "GOT_SIGTERM=1; Print Got SIGTERM ..." SIGTERM while [ -z "$GOT_SIGTERM" ] && sleep 1; do for pid in $PIDS; do [ ! -e /proc/$pid ] && Print Unexpected error! && exit done done } # Start here Main