diff options
Diffstat (limited to 'scripts/wsrep_sst_rsync.sh')
-rw-r--r-- | scripts/wsrep_sst_rsync.sh | 250 |
1 files changed, 123 insertions, 127 deletions
diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 29c9cd43470..28dfed18218 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -17,7 +17,7 @@ # Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston # MA 02110-1335 USA. -# This is a reference script for rsync-based state snapshot tansfer +# This is a reference script for rsync-based state snapshot transfer RSYNC_REAL_PID=0 # rsync process id STUNNEL_REAL_PID=0 # stunnel process id @@ -25,9 +25,6 @@ STUNNEL_REAL_PID=0 # stunnel process id 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 wsrep_check_datadir @@ -37,13 +34,14 @@ cleanup_joiner() { local failure=0 - wsrep_log_info "Joiner cleanup: rsync PID=$RSYNC_REAL_PID, stunnel PID=$STUNNEL_REAL_PID" + wsrep_log_info "Joiner cleanup: rsync PID=$RSYNC_REAL_PID," \ + "stunnel PID=$STUNNEL_REAL_PID" if [ -n "$STUNNEL" ]; then if cleanup_pid $STUNNEL_REAL_PID "$STUNNEL_PID" "$STUNNEL_CONF"; then if [ $RSYNC_REAL_PID -eq 0 ]; then if [ -r "$RSYNC_PID" ]; then - RSYNC_REAL_PID=$(cat "$RSYNC_PID" 2>/dev/null) + RSYNC_REAL_PID=$(cat "$RSYNC_PID" 2>/dev/null || :) if [ -z "$RSYNC_REAL_PID" ]; then RSYNC_REAL_PID=0 fi @@ -81,18 +79,18 @@ check_pid_and_port() local utils='rsync|stunnel' - if ! check_port "$pid" "$port" "$utils"; then + if ! check_port $pid "$port" "$utils"; then local port_info local busy=0 if [ $lsof_available -ne 0 ]; then port_info=$(lsof -Pnl -i ":$port" 2>/dev/null | \ - grep -F '(LISTEN)') + grep -F '(LISTEN)') echo "$port_info" | \ grep -q -E "[[:space:]](\\*|\\[?::\\]?):$port[[:space:]]" && busy=1 else local filter='([^[:space:]]+[[:space:]]+){4}[^[:space:]]+' - if [ $sockstat_available -eq 1 ]; then + if [ $sockstat_available -ne 0 ]; then local opts='-p' if [ "$OS" = 'FreeBSD' ]; then # sockstat on FreeBSD requires the "-s" option @@ -112,19 +110,21 @@ check_pid_and_port() fi if [ $busy -eq 0 ]; then - if echo "$port_info" | grep -qw -F "[$addr]:$port" || \ - echo "$port_info" | grep -qw -F -- "$addr:$port" + if ! echo "$port_info" | grep -qw -F "[$addr]:$port" && \ + ! echo "$port_info" | grep -qw -F -- "$addr:$port" then - busy=1 + if ! ps -p $pid >/dev/null 2>&1; then + wsrep_log_error \ + "rsync or stunnel daemon (PID: $pid)" \ + "terminated unexpectedly." + exit 16 # EBUSY + fi + return 1 fi fi - if [ $busy -eq 0 ]; then - return 1 - fi - - if ! check_port "$pid" "$port" "$utils"; then - wsrep_log_error "rsync or stunnel daemon port '$port' " \ + if ! check_port $pid "$port" "$utils"; then + wsrep_log_error "rsync or stunnel daemon port '$port'" \ "has been taken by another program" exit 16 # EBUSY fi @@ -199,60 +199,23 @@ INNODB_UNDO_DIR=$(pwd -P) cd "$OLD_PWD" -# Old filter - include everything except selected -# FILTER=(--exclude '*.err' --exclude '*.pid' --exclude '*.sock' \ -# --exclude '*.conf' --exclude core --exclude 'galera.*' \ -# --exclude grastate.txt --exclude '*.pem' \ -# --exclude '*.[0-9][0-9][0-9][0-9][0-9][0-9]' --exclude '*.index') +encgroups='--mysqld|sst' -# New filter - exclude everything except dirs (schemas) and innodb files -FILTER="-f '- /lost+found' - -f '- /.zfs' - -f '- /.fseventsd' - -f '- /.Trashes' - -f '- /.pid' - -f '- /.conf' - -f '+ /wsrep_sst_binlog.tar' - -f '- $INNODB_DATA_HOME_DIR/ib_lru_dump' - -f '- $INNODB_DATA_HOME_DIR/ibdata*' - -f '+ $INNODB_UNDO_DIR/undo*' - -f '+ /*/' - -f '- /*'" - -# old-style SSL config -SSTKEY=$(parse_cnf 'sst' 'tkey') -SSTCERT=$(parse_cnf 'sst' 'tcert') -SSTCA=$(parse_cnf 'sst' 'tca') - -SST_SECTIONS="--mysqld|sst" +check_server_ssl_config -check_server_ssl_config() -{ - SSTKEY=$(parse_cnf "$SST_SECTIONS" 'ssl-key') - SSTCERT=$(parse_cnf "$SST_SECTIONS" 'ssl-cert') - SSTCA=$(parse_cnf "$SST_SECTIONS" 'ssl-ca') -} +SSTKEY="$tkey" +SSTCERT="$tpem" +SSTCA="$tcert" +SSTCAP="$tcap" -SSLMODE=$(parse_cnf "$SST_SECTIONS" 'ssl-mode' | tr [:lower:] [:upper:]) - -# no old-style SSL config in [sst], check for new one: -if [ -z "$SSTKEY" -a -z "$SSTCERT" -a -z "$SSTCA" ]; then - check_server_ssl_config -fi - -SSTPATH=0 -if [ -n "$SSTCA" ]; then - SSTCA=$(trim_string "$SSTCA") - if [ "${SSTCA%/}" != "$SSTCA" ]; then - SSTPATH=1 - fi -fi +SSLMODE=$(parse_cnf "$encgroups" 'ssl-mode' | tr [:lower:] [:upper:]) if [ -z "$SSLMODE" ]; then # Implicit verification if CA is set and the SSL mode # is not specified by user: - if [ -n "$SSTCA" ]; then - if [ -n "$(command -v stunnel)" ]; then + if [ -n "$SSTCA$SSTCAP" ]; then + STUNNEL_BIN=$(commandex 'stunnel') + if [ -n "$STUNNEL_BIN" ]; then SSLMODE='VERIFY_CA' fi # Require SSL by default if SSL key and cert are present: @@ -261,28 +224,28 @@ if [ -z "$SSLMODE" ]; then fi fi -if [ -n "$SSTCERT" -a -n "$SSTKEY" ]; then +if [ -n "$SSTKEY" -a -n "$SSTCERT" ]; then verify_cert_matches_key "$SSTCERT" "$SSTKEY" fi -if [ -n "$SSTCA" ]; then - if [ $SSTPATH -eq 0 ]; then +CAFILE_OPT="" +CAPATH_OPT="" +if [ -n "$SSTCA$SSTCAP" ]; then + if [ -n "$SSTCA" ]; then CAFILE_OPT="CAfile = $SSTCA" - else - CAFILE_OPT="CApath = $SSTCA" + fi + if [ -n "$SSTCAP" ]; then + CAPATH_OPT="CApath = $SSTCAP" fi if [ -n "$SSTCERT" ]; then - verify_ca_matches_cert "$SSTCA" "$SSTCERT" $SSTPATH + verify_ca_matches_cert "$SSTCERT" "$SSTCA" "$SSTCAP" fi -else - CAFILE_OPT="" fi VERIFY_OPT="" CHECK_OPT="" CHECK_OPT_LOCAL="" -if [ "${SSLMODE#VERIFY}" != "$SSLMODE" ] -then +if [ "${SSLMODE#VERIFY}" != "$SSLMODE" ]; then case "$SSLMODE" in 'VERIFY_IDENTITY') VERIFY_OPT='verifyPeer = yes' @@ -295,7 +258,7 @@ then exit 22 # EINVAL ;; esac - if [ -z "$SSTCA" ]; then + if [ -z "$SSTCA$SSTCAP" ]; then wsrep_log_error "Can't have ssl-mode='$SSLMODE' without CA file or path" exit 22 # EINVAL fi @@ -318,9 +281,12 @@ fi STUNNEL="" if [ -n "$SSLMODE" -a "$SSLMODE" != 'DISABLED' ]; then - STUNNEL_BIN="$(command -v stunnel)" + if [ -z "${STUNNEL_BIN+x}" ]; then + STUNNEL_BIN=$(commandex 'stunnel') + fi if [ -n "$STUNNEL_BIN" ]; then - wsrep_log_info "Using stunnel for SSL encryption: CA: '$SSTCA', ssl-mode='$SSLMODE'" + wsrep_log_info "Using stunnel for SSL encryption: CA: '$SSTCA'," \ + "CAPATH='$SSTCAP', ssl-mode='$SSLMODE'" STUNNEL="$STUNNEL_BIN $STUNNEL_CONF" fi fi @@ -340,6 +306,7 @@ then key = $SSTKEY cert = $SSTCERT ${CAFILE_OPT} +${CAPATH_OPT} foreground = yes pid = $STUNNEL_PID debug = warning @@ -354,8 +321,9 @@ EOF [ -f "$STUNNEL_CONF" ] && rm -f "$STUNNEL_CONF" fi - if [ $WSREP_SST_OPT_BYPASS -eq 0 ] - then + RC=0 + + if [ $WSREP_SST_OPT_BYPASS -eq 0 ]; then FLUSHED="$WSREP_SST_OPT_DATA/tables_flushed" ERROR="$WSREP_SST_OPT_DATA/sst_error" @@ -370,11 +338,11 @@ 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 -F ':' "$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" ] - then + if [ -f "$ERROR" ]; then # Flush tables operation failed. rm -f "$ERROR" exit 255 @@ -387,24 +355,22 @@ EOF sync - if [ -n "$WSREP_SST_OPT_BINLOG" ] + if [ -n "$WSREP_SST_OPT_BINLOG" -a -d "${BINLOG_DIRNAME:-}" ] then # Prepare binlog files cd "$BINLOG_DIRNAME" - binlog_files_full=$(tail -n $BINLOG_N_FILES "$WSREP_SST_OPT_BINLOG_INDEX") - + binlog_files_full=$(tail -n $BINLOG_N_FILES \ + "$WSREP_SST_OPT_BINLOG_INDEX") binlog_files="" - for ii in $binlog_files_full - do - binlog_file=$(basename "$ii") - binlog_files="$binlog_files $binlog_file" + for file in $binlog_files_full; do + binlog_file=$(basename "$file") + binlog_files="$binlog_files${binlog_files:+ }'$binlog_file'" done - if [ -n "$binlog_files" ] - then + if [ -n "$binlog_files" ]; then wsrep_log_info "Preparing binlog files for transfer:" - tar -cvf "$BINLOG_TAR_FILE" $binlog_files >&2 + eval tar -cvf "'$BINLOG_TAR_FILE'" $binlog_files >&2 fi cd "$OLD_PWD" @@ -417,9 +383,29 @@ EOF WHOLE_FILE_OPT="--whole-file" fi - # first, the normal directories, so that we can detect incompatible protocol - RC=0 - eval rsync ${STUNNEL:+"'--rsh=$STUNNEL'"} \ +# Old filter - include everything except selected +# FILTER=(--exclude '*.err' --exclude '*.pid' --exclude '*.sock' \ +# --exclude '*.conf' --exclude core --exclude 'galera.*' \ +# --exclude grastate.txt --exclude '*.pem' \ +# --exclude '*.[0-9][0-9][0-9][0-9][0-9][0-9]' --exclude '*.index') + +# New filter - exclude everything except dirs (schemas) and innodb files +FILTER="-f '- /lost+found' + -f '- /.zfs' + -f '- /.fseventsd' + -f '- /.Trashes' + -f '- /.pid' + -f '- /.conf' + -f '+ /wsrep_sst_binlog.tar' + -f '- $INNODB_DATA_HOME_DIR/ib_lru_dump' + -f '- $INNODB_DATA_HOME_DIR/ibdata*' + -f '+ $INNODB_UNDO_DIR/undo*' + -f '+ /*/' + -f '- /*'" + + # first, the normal directories, so that we can detect + # incompatible protocol: + eval rsync ${STUNNEL:+"--rsh='$STUNNEL'"} \ --owner --group --perms --links --specials \ --ignore-times --inplace --dirs --delete --quiet \ $WHOLE_FILE_OPT $FILTER "'$WSREP_SST_OPT_DATA/'" \ @@ -430,8 +416,9 @@ EOF case $RC in 12) RC=71 # EPROTO wsrep_log_error \ - "rsync server on the other end has incompatible protocol. " \ - "Make sure you have the same version of rsync on all nodes." + "rsync server on the other end has incompatible" \ + "protocol. Make sure you have the same version of" \ + "rsync on all nodes." ;; 22) RC=12 # ENOMEM ;; @@ -472,7 +459,7 @@ EOF cd "$WSREP_SST_OPT_DATA" - backup_threads=$(parse_cnf "--mysqld|sst" 'backup-threads') + backup_threads=$(parse_cnf '--mysqld|sst' 'backup-threads') if [ -z "$backup_threads" ]; then get_proc backup_threads=$nproc @@ -481,9 +468,9 @@ EOF find . -maxdepth 1 -mindepth 1 -type d -not -name 'lost+found' \ -not -name '.zfs' -print0 | xargs -I{} -0 -P $backup_threads \ rsync ${STUNNEL:+--rsh="$STUNNEL"} \ - --owner --group --perms --links --specials \ - --ignore-times --inplace --recursive --delete --quiet \ - $WHOLE_FILE_OPT --exclude '*/ib_logfile*' --exclude '*/aria_log.*' \ + --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=$? @@ -514,7 +501,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" >&2 || RC=$? + + if [ $RC -ne 0 ]; then + wsrep_log_error "rsync $MAGIC_FILE returned code $RC:" + exit 255 # unknown error + fi echo "done $STATE" @@ -527,12 +520,11 @@ elif [ "$WSREP_SST_OPT_ROLE" = 'joiner' ] then check_sockets_utils - SST_PID="$WSREP_SST_OPT_DATA/wsrep_rsync_sst.pid" + SST_PID="$WSREP_SST_OPT_DATA/wsrep_sst.pid" # give some time for previous SST to complete: check_round=0 - while check_pid "$SST_PID" 0 - do + while check_pid "$SST_PID" 0 'wsrep_sst_'; do wsrep_log_info "previous SST is not completed, waiting for it to exit" check_round=$(( check_round + 1 )) if [ $check_round -eq 10 ]; then @@ -542,11 +534,13 @@ then sleep 1 done + echo $$ > "$SST_PID" + # give some time for stunnel from the previous SST to complete: check_round=0 - while check_pid "$STUNNEL_PID" 1 - do - wsrep_log_info "lingering stunnel daemon found at startup, waiting for it to exit" + while check_pid "$STUNNEL_PID" 1; do + wsrep_log_info "Lingering stunnel daemon found at startup," \ + "waiting for it to exit" check_round=$(( check_round + 1 )) if [ $check_round -eq 10 ]; then wsrep_log_error "stunnel daemon already running." @@ -561,9 +555,9 @@ then # give some time for rsync from the previous SST to complete: check_round=0 - while check_pid "$RSYNC_PID" 1 - do - wsrep_log_info "lingering rsync daemon found at startup, waiting for it to exit" + while check_pid "$RSYNC_PID" 1; do + wsrep_log_info "Lingering rsync daemon found at startup," \ + "waiting for it to exit" check_round=$(( check_round + 1 )) if [ $check_round -eq 10 ]; then wsrep_log_error "rsync daemon already running." @@ -575,9 +569,7 @@ then [ -f "$MAGIC_FILE" ] && rm -f "$MAGIC_FILE" [ -f "$BINLOG_TAR_FILE" ] && rm -f "$BINLOG_TAR_FILE" - if [ -z "$STUNNEL" ]; then - [ -f "$STUNNEL_CONF" ] && rm -f "$STUNNEL_CONF" - fi + [ -z "$STUNNEL" -a -f "$STUNNEL_CONF" ] && rm -f "$STUNNEL_CONF" ADDR="$WSREP_SST_OPT_ADDR" RSYNC_PORT="$WSREP_SST_OPT_PORT" @@ -626,21 +618,21 @@ EOF RSYNC_ADDR="*" fi - echo $$ > "$SST_PID" - - if [ -z "$STUNNEL" ] - then - rsync --daemon --no-detach --port "$RSYNC_PORT" --config "$RSYNC_CONF" $RSYNC_EXTRA_ARGS & + if [ -z "$STUNNEL" ]; then + rsync --daemon --no-detach --port "$RSYNC_PORT" \ + --config "$RSYNC_CONF" $RSYNC_EXTRA_ARGS & RSYNC_REAL_PID=$! TRANSFER_REAL_PID=$RSYNC_REAL_PID TRANSFER_PID="$RSYNC_PID" else # Let's check if the path to the config file contains a space? + RSYNC_BIN=$(commandex 'rsync') if [ "${RSYNC_CONF#* }" = "$RSYNC_CONF" ]; then cat << EOF > "$STUNNEL_CONF" key = $SSTKEY cert = $SSTCERT ${CAFILE_OPT} +${CAPATH_OPT} foreground = yes pid = $STUNNEL_PID debug = warning @@ -650,17 +642,18 @@ ${CHECK_OPT} ${CHECK_OPT_LOCAL} [rsync] accept = $STUNNEL_ACCEPT -exec = $(command -v rsync) +exec = $RSYNC_BIN execargs = rsync --server --daemon --config=$RSYNC_CONF . EOF else # The path contains a space, so we will run it via # shell with "eval" command: - export RSYNC_CMD="eval $(command -v rsync) --server --daemon --config='$RSYNC_CONF' ." + export RSYNC_CMD="eval '$RSYNC_BIN' --server --daemon --config='$RSYNC_CONF' ." cat << EOF > "$STUNNEL_CONF" key = $SSTKEY cert = $SSTCERT ${CAFILE_OPT} +${CAPATH_OPT} foreground = yes pid = $STUNNEL_PID debug = warning @@ -688,7 +681,8 @@ EOF # find out my Common Name get_openssl if [ -z "$OPENSSL_BINARY" ]; then - wsrep_log_error 'openssl not found but it is required for authentication' + wsrep_log_error \ + 'openssl not found but it is required for authentication' exit 42 fi CN=$("$OPENSSL_BINARY" x509 -noout -subject -in "$SSTCERT" | \ @@ -703,7 +697,8 @@ EOF ADDR="$WSREP_SST_OPT_HOST" fi - until check_pid_and_port "$TRANSFER_PID" $TRANSFER_REAL_PID "$RSYNC_ADDR_UNESCAPED" "$RSYNC_PORT" + until check_pid_and_port "$TRANSFER_PID" $TRANSFER_REAL_PID \ + "$RSYNC_ADDR_UNESCAPED" "$RSYNC_PORT" do sleep 0.2 done @@ -722,7 +717,7 @@ EOF if ! ps -p $MYSQLD_PID >/dev/null 2>&1 then wsrep_log_error \ - "Parent mysqld process (PID: $MYSQLD_PID) terminated unexpectedly." + "Parent mysqld process (PID: $MYSQLD_PID) terminated unexpectedly." kill -- -$MYSQLD_PID sleep 1 exit 32 @@ -768,10 +763,11 @@ EOF if [ -r "$MAGIC_FILE" ]; then if [ -n "$MY_SECRET" ]; then # check donor supplied secret - SECRET=$(grep -F -- "$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'" + wsrep_log_info "Donor: '$SECRET', my: '$MY_SECRET'" exit 32 fi # remove secret from the magic file, and output |