diff options
Diffstat (limited to 'scripts/wsrep_sst_rsync.sh')
-rw-r--r-- | scripts/wsrep_sst_rsync.sh | 178 |
1 files changed, 93 insertions, 85 deletions
diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 92fdc28f643..70e4a3326a1 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -23,13 +23,13 @@ RSYNC_PID= # rsync pid file RSYNC_CONF= # rsync configuration file RSYNC_REAL_PID= # rsync process id -OS=$(uname) +OS="$(uname)" [ "$OS" = 'Darwin' ] && export -n LD_LIBRARY_PATH # Setting the path for lsof on CentOS export PATH="/usr/sbin:/sbin:$PATH" -. $(dirname $0)/wsrep_sst_common +. $(dirname "$0")/wsrep_sst_common wsrep_check_datadir wsrep_check_programs rsync @@ -48,7 +48,7 @@ cleanup_joiner() rm -rf "$MAGIC_FILE" rm -rf "$RSYNC_PID" wsrep_log_info "Joiner cleanup done." - if [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then + if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then wsrep_cleanup_progress_file fi } @@ -57,68 +57,71 @@ cleanup_joiner() check_pid() { local pid_file="$1" - [ -r "$pid_file" ] && ps -p $(cat "$pid_file") >/dev/null 2>&1 + [ -r "$pid_file" ] && ps -p $(cat "$pid_file") 2>&1 >/dev/null } check_pid_and_port() { local pid_file="$1" local rsync_pid=$2 - local rsync_addr=$3 - local rsync_port=$4 - - case $OS in - FreeBSD) - local port_info="$(sockstat -46lp ${rsync_port} 2>/dev/null | \ - grep ":${rsync_port}")" - local is_rsync="$(echo $port_info | \ - grep -E '[[:space:]]+(rsync|stunnel)[[:space:]]+'"$rsync_pid" 2>/dev/null)" - ;; - *) - if [ ! -x "$(command -v lsof)" ]; then - wsrep_log_error "lsof tool not found in PATH! Make sure you have it installed." - exit 2 # ENOENT - fi - local port_info="$(lsof -i :$rsync_port -Pn 2>/dev/null | \ - grep "(LISTEN)")" - local is_rsync="$(echo $port_info | \ - grep -E '^(rsync|stunnel)[[:space:]]+'"$rsync_pid" 2>/dev/null)" - ;; - esac + local rsync_addr="$3" + local rsync_port="$4" + + if [ -z "$rsync_port" -o -z "$rsync_addr" -o -z "$rsync_pid" ]; then + wsrep_log_error "check_pid_and_port(): bad arguments" + exit 2 # ENOENT + fi - local is_listening_all="$(echo $port_info | \ - grep "*:$rsync_port" 2>/dev/null)" - local is_listening_addr="$(echo $port_info | \ - grep -F "$rsync_addr:$rsync_port" 2>/dev/null)" + local port_info is_rsync + + if [ $lsof_available -ne 0 ]; then + port_info=$(lsof -i ":$rsync_port" -Pn 2>/dev/null | \ + grep -F '(LISTEN)') + is_rsync=$(echo "$port_info" | \ + grep -E "^(rsync|stunnel)[^[:space:]]*[[:space:]]+$rsync_pid[[:space:]]+") + elif [ $sockstat_available -ne 0 ]; then + port_info=$(sockstat -p "$rsync_port" 2>/dev/null | \ + grep -F 'LISTEN') + is_rsync=$(echo "$port_info" | \ + grep -E "[[:space:]]+(rsync|stunnel)[^[:space:]]*[[:space:]]+$rsync_pid[[:space:]]+") + elif [ $ss_available -ne 0 ]; then + port_info=$(ss -H -p -n -l "( sport = :$rsync_port )" 2>/dev/null) + is_rsync=$(echo "$port_info" | \ + grep -E "users:\\(.*\\(\"(rsync|stunnel)[^[:space:]]*\".*\<pid=$rsync_pid\>.*\\)") + else + wsrep_log_error "unknown sockets utility" + exit 2 # ENOENT + fi - if [ ! -z "$is_listening_all" -o ! -z "$is_listening_addr" ]; then - if [ -z "$is_rsync" ]; then - wsrep_log_error "rsync daemon port '$rsync_port' has been taken" + if [ -z "$is_rsync" ]; then + local is_listening_all + if [ $lsof_available -ne 0 ]; then + is_listening_all=$(echo "$port_info" | \ + grep -E "[[:space:]](\\*|\\[?::\\]?):$rsync_port[[:space:]]") + else + if [ $sockstat_available -eq 0 ]; then + port_info=$(echo "$port_info" | grep -q -F 'users:(') + fi + port_info=$(echo "$port_info" | \ + grep -E "[^[:space:]]+[[:space:]]+[^[:space:]]+[[:space:]]+[^[:space:]]+[[:space:]]+[^[:space:]]+[[:space:]]+[^[:space:]]+" -o) + is_listening_all=$(echo "$port_info" | \ + grep -E "[[:space:]](\\*|\\[?::\\]?):$rsync_port\$") + fi + local is_listening_addr=$(echo "$port_info" | \ + grep -w -F -- "$rsync_addr:$rsync_port") + if [ -z "$is_listening_addr" ]; then + is_listening_addr=$(echo "$port_info" | \ + grep -w -F "[$rsync_addr]:$rsync_port") + fi + if [ -n "$is_listening_all" -o -n "$is_listening_addr" ]; then + wsrep_log_error "rsync or stunnel daemon port '$rsync_port' " \ + "has been taken by another program" exit 16 # EBUSY fi + return 1 fi - check_pid "$pid_file" && \ - [ -n "$port_info" ] && [ -n "$is_rsync" ] && \ - [ $(cat "$pid_file") -eq $rsync_pid ] -} -is_local_ip() -{ - local address="$1" - local get_addr_bin="$(command -v ifconfig)" - if [ -z "$get_addr_bin" ] - then - get_addr_bin="$(command -v ip) address show" - # Add an slash at the end, so we don't get false positive : 172.18.0.4 matches 172.18.0.41 - # ip output format is "X.X.X.X/mask" - address="$address/" - else - # Add an space at the end, so we don't get false positive : 172.18.0.4 matches 172.18.0.41 - # ifconfig output format is "X.X.X.X " - address="$address " - fi - - $get_addr_bin | grep -F "$address" > /dev/null + check_pid "$pid_file" && [ $(cat "$pid_file") -eq $rsync_pid ] } STUNNEL_CONF="$WSREP_SST_OPT_DATA/stunnel.conf" @@ -225,11 +228,11 @@ check_server_ssl_config() SSLMODE=$(parse_cnf 'sst' 'ssl-mode' | tr [:lower:] [:upper:]) -if [ -z "$SSTKEY" -a -z "$SSTCERT" ] +if [ -z "$SSTKEY" -a -z "$SSTCERT" -a -z "$SSTCA" ] then # no old-style SSL config in [sst], check for new one check_server_ssl_config 'sst' - if [ -z "$SSTKEY" -a -z "$SSTCERT" ]; then + if [ -z "$SSTKEY" -a -z "$SSTCERT" -a -z "$SSTCA" ]; then check_server_ssl_config '--mysqld' fi fi @@ -279,7 +282,7 @@ fi STUNNEL="" if [ -n "$SSLMODE" -a "$SSLMODE" != 'DISABLED' ] && wsrep_check_programs stunnel then - wsrep_log_info "Using stunnel for SSL encryption: CAfile: $SSTCA, SSLMODE: $SSLMODE" + wsrep_log_info "Using stunnel for SSL encryption: CAfile: '$SSTCA', SSLMODE: '$SSLMODE'" STUNNEL="stunnel $STUNNEL_CONF" fi @@ -296,7 +299,7 @@ foreground = yes pid = $STUNNEL_PID debug = warning client = yes -connect = ${WSREP_SST_OPT_ADDR%/*} +connect = $WSREP_SST_OPT_HOST_UNESCAPED:$WSREP_SST_OPT_PORT TIMEOUTclose = 0 ${VERIFY_OPT} EOF @@ -322,7 +325,7 @@ EOF # (b) Cluster state ID & wsrep_gtid_domain_id to be written to the file, OR # (c) ERROR file, in case flush tables operation failed. - while [ ! -r "$FLUSHED" ] && ! grep -q ':' "$FLUSHED" >/dev/null 2>&1 + while [ ! -r "$FLUSHED" ] && ! grep -q -F ':' "$FLUSHED" >/dev/null 2>&1 do # Check whether ERROR file exists. if [ -f "$ERROR" ] @@ -365,15 +368,14 @@ EOF # first, the normal directories, so that we can detect incompatible protocol RC=0 - eval rsync ${STUNNEL:+--rsh=\"$STUNNEL\"} \ + eval rsync "'${STUNNEL:+--rsh=$STUNNEL}'" \ --owner --group --perms --links --specials \ --ignore-times --inplace --dirs --delete --quiet \ - $WHOLE_FILE_OPT ${FILTER} "$WSREP_SST_OPT_DATA/" \ - rsync://$WSREP_SST_OPT_ADDR >&2 || RC=$? + $WHOLE_FILE_OPT $FILTER "'$WSREP_SST_OPT_DATA/'" \ + "'rsync://$WSREP_SST_OPT_ADDR'" >&2 || RC=$? if [ $RC -ne 0 ]; then wsrep_log_error "rsync returned code $RC:" - case $RC in 12) RC=71 # EPROTO wsrep_log_error \ @@ -394,7 +396,7 @@ EOF --ignore-times --inplace --dirs --delete --quiet \ $WHOLE_FILE_OPT -f '+ /ibdata*' -f '+ /ib_lru_dump' \ -f '- **' "$INNODB_DATA_HOME_DIR/" \ - rsync://$WSREP_SST_OPT_ADDR-data_dir >&2 || RC=$? + "rsync://$WSREP_SST_OPT_ADDR-data_dir" >&2 || RC=$? if [ $RC -ne 0 ]; then wsrep_log_error "rsync innodb_data_home_dir returned code $RC:" @@ -405,28 +407,32 @@ EOF rsync ${STUNNEL:+--rsh="$STUNNEL"} \ --owner --group --perms --links --specials \ --ignore-times --inplace --dirs --delete --quiet \ - $WHOLE_FILE_OPT -f '+ /ib_logfile[0-9]*' -f '+ /aria_log.*' -f '+ /aria_log_control' -f '- **' "$WSREP_LOG_DIR/" \ - rsync://$WSREP_SST_OPT_ADDR-log_dir >&2 || RC=$? + $WHOLE_FILE_OPT -f '+ /ib_logfile[0-9]*' -f '+ /aria_log.*' \ + -f '+ /aria_log_control' -f '- **' "$WSREP_LOG_DIR/" \ + "rsync://$WSREP_SST_OPT_ADDR-log_dir" >&2 || RC=$? if [ $RC -ne 0 ]; then wsrep_log_error "rsync innodb_log_group_home_dir returned code $RC:" exit 255 # unknown error fi - # then, we parallelize the transfer of database directories, use . so that pathconcatenation works + # then, we parallelize the transfer of database directories, + # use . so that path concatenation works: + cd "$WSREP_SST_OPT_DATA" count=1 - [ "$OS" = "Linux" ] && count=$(grep -c processor /proc/cpuinfo) - [ "$OS" = "Darwin" -o "$OS" = "FreeBSD" ] && count=$(sysctl -n hw.ncpu) + [ "$OS" = 'Linux' ] && count=$(grep -c processor /proc/cpuinfo) + [ "$OS" = 'Darwin' -o "$OS" = 'FreeBSD' ] && count=$(sysctl -n hw.ncpu) - find . -maxdepth 1 -mindepth 1 -type d -not -name "lost+found" -not -name ".zfs" \ - -print0 | xargs -I{} -0 -P $count \ + find . -maxdepth 1 -mindepth 1 -type d -not -name 'lost+found' \ + -not -name '.zfs' -print0 | xargs -I{} -0 -P $count \ rsync ${STUNNEL:+--rsh="$STUNNEL"} \ --owner --group --perms --links --specials \ --ignore-times --inplace --recursive --delete --quiet \ - $WHOLE_FILE_OPT --exclude '*/ib_logfile*' --exclude "*/aria_log.*" --exclude "*/aria_log_control" "$WSREP_SST_OPT_DATA"/{}/ \ - rsync://$WSREP_SST_OPT_ADDR/{} >&2 || RC=$? + $WHOLE_FILE_OPT --exclude '*/ib_logfile*' --exclude '*/aria_log.*' \ + --exclude '*/aria_log_control' "$WSREP_SST_OPT_DATA/{}/" \ + "rsync://$WSREP_SST_OPT_ADDR/{}" >&2 || RC=$? cd "$OLD_PWD" @@ -455,13 +461,13 @@ EOF fi rsync ${STUNNEL:+--rsh="$STUNNEL"} \ - --archive --quiet --checksum "$MAGIC_FILE" rsync://$WSREP_SST_OPT_ADDR + --archive --quiet --checksum "$MAGIC_FILE" "rsync://$WSREP_SST_OPT_ADDR" echo "done $STATE" elif [ "$WSREP_SST_OPT_ROLE" = 'joiner' ] then - wsrep_check_programs lsof + check_sockets_utils touch "$SST_PROGRESS_FILE" MYSQLD_PID="$WSREP_SST_OPT_PARENT" @@ -488,6 +494,7 @@ then ADDR="$WSREP_SST_OPT_ADDR" RSYNC_PORT="$WSREP_SST_OPT_PORT" RSYNC_ADDR="$WSREP_SST_OPT_HOST" + RSYNC_ADDR_UNESCAPED="$WSREP_SST_OPT_HOST_UNESCAPED" trap "exit 32" HUP PIPE trap "exit 3" INT TERM ABRT @@ -519,10 +526,10 @@ EOF # rm -rf "$DATA"/ib_logfile* # we don't want old logs around # If the IP is local listen only in it - if is_local_ip "$RSYNC_ADDR" + if is_local_ip "$RSYNC_ADDR_UNESCAPED" then - RSYNC_EXTRA_ARGS="--address $RSYNC_ADDR" - STUNNEL_ACCEPT="$RSYNC_ADDR:$RSYNC_PORT" + RSYNC_EXTRA_ARGS="--address $RSYNC_ADDR_UNESCAPED" + STUNNEL_ACCEPT="$RSYNC_ADDR_UNESCAPED:$RSYNC_PORT" else # Not local, possibly a NAT, listen on all interfaces RSYNC_EXTRA_ARGS="" @@ -533,7 +540,7 @@ EOF if [ -z "$STUNNEL" ] then - rsync --daemon --no-detach --port "$RSYNC_PORT" --config "$RSYNC_CONF" ${RSYNC_EXTRA_ARGS} & + rsync --daemon --no-detach --port "$RSYNC_PORT" --config "$RSYNC_CONF" $RSYNC_EXTRA_ARGS & RSYNC_REAL_PID=$! else cat << EOF > "$STUNNEL_CONF" @@ -543,18 +550,19 @@ ${CAFILE_OPT} foreground = yes pid = $STUNNEL_PID debug = warning +debug = 6 client = no [rsync] accept = $STUNNEL_ACCEPT exec = $(command -v rsync) -execargs = rsync --server --daemon --config='$RSYNC_CONF' . +execargs = rsync --server --daemon --config=$RSYNC_CONF . EOF stunnel "$STUNNEL_CONF" & RSYNC_REAL_PID=$! RSYNC_PID="$STUNNEL_PID" fi - until check_pid_and_port "$RSYNC_PID" "$RSYNC_REAL_PID" "$RSYNC_ADDR" "$RSYNC_PORT" + until check_pid_and_port "$RSYNC_PID" "$RSYNC_REAL_PID" "$RSYNC_ADDR_UNESCAPED" "$RSYNC_PORT" do sleep 0.2 done @@ -571,10 +579,10 @@ EOF exit 42 fi CN=$("$OPENSSL_BINARY" x509 -noout -subject -in "$SSTCERT" | \ - tr "," "\n" | grep "CN =" | cut -d= -f2 | sed s/^\ // | \ + tr "," "\n" | grep -F 'CN =' | cut -d= -f2 | sed s/^\ // | \ sed s/\ %//) fi - MY_SECRET=$(wsrep_gen_secret) + MY_SECRET="$(wsrep_gen_secret)" # Add authentication data to address ADDR="$CN:$MY_SECRET@$WSREP_SST_OPT_HOST" else @@ -624,7 +632,7 @@ EOF if [ -r "$MAGIC_FILE" ] then # check donor supplied secret - SECRET=$(grep "$SECRET_TAG " "$MAGIC_FILE" 2>/dev/null | cut -d ' ' -f 2) + SECRET=$(grep -F -- "$SECRET_TAG " "$MAGIC_FILE" 2>/dev/null | cut -d ' ' -f 2) if [ "$SECRET" != "$MY_SECRET" ]; then wsrep_log_error "Donor does not know my secret!" wsrep_log_info "Donor:'$SECRET', my:'$MY_SECRET'" @@ -632,7 +640,7 @@ EOF fi # remove secret from magic file - grep -v "$SECRET_TAG " "$MAGIC_FILE" > "$MAGIC_FILE.new" + grep -v -F -- "$SECRET_TAG " "$MAGIC_FILE" > "$MAGIC_FILE.new" mv "$MAGIC_FILE.new" "$MAGIC_FILE" # UUID:seqno & wsrep_gtid_domain_id is received here. @@ -643,7 +651,7 @@ EOF fi wsrep_cleanup_progress_file -# cleanup_joiner +# cleanup_joiner else wsrep_log_error "Unrecognized role: '$WSREP_SST_OPT_ROLE'" exit 22 # EINVAL |