From c8a177e2c2850d01193193e1ccd072f02f0b4ae2 Mon Sep 17 00:00:00 2001 From: Christoph Date: Wed, 6 Nov 2019 00:38:54 +0100 Subject: [PATCH] repair_mysql_tables.sh: support multiple MySQL instances. --- repair_mysql_tables.sh | 382 +++++++++++++++++++++++++++-------------- 1 file changed, 253 insertions(+), 129 deletions(-) diff --git a/repair_mysql_tables.sh b/repair_mysql_tables.sh index 09e3c03..99fec84 100755 --- a/repair_mysql_tables.sh +++ b/repair_mysql_tables.sh @@ -10,8 +10,11 @@ tmp_log_file="$(mktemp)" # - Variable settings # ------------- DEFAULT_MYSQL_CREDENTIAL_ARGS="--defaults-file=/usr/local/mysql/sys-maint.cnf" + ALL_DATABASES=false +DATABASE_NAME_NEEDED=true + # ------------- # --- Some functions @@ -24,7 +27,7 @@ usage() { [[ $terminal ]] && echo -e " \033[1mUsage:\033[m - $(basename $0) + $(basename $0) [DB-Name] \033[1mDescription\033[m @@ -32,6 +35,8 @@ usage() { command 'REPAIR TABLE'. If this was successfully, also 'OPTIMIZE TABLE' command will be triggered. + If no database was given at command line all tables of ALL databases are checked. + \033[1mOptions\033[m No Options available @@ -140,6 +145,16 @@ echo_skipped() { fi } +is_number() { + + return $(test ! -z "${1##*[!0-9]*}" > /dev/null 2>&1); + + # - also possible + # - + #[[ ! -z "${1##*[!0-9]*}" ]] && return 0 || return 1 + #return $([[ ! -z "${1##*[!0-9]*}" ]]) +} + trim() { local var="$*" var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters @@ -182,32 +197,10 @@ fi # ------------- if [[ -n "$1" ]] ; then - GIVEN_DATABASE="$1" + DATABASE_NAME_NEEDED=false + DATABASE_NAME="$1" else - GIVEN_DATABASE="" - if $terminal ; then - - warn "No Databses given!" - - echo "" - echo -e " \033[33mType upper case \033[1mYES\033[m\033[33m to trigger 'REPAIR TABLES' on all tables of all databases\033[m" - echo "" - echo -en " \033[37m\033[1mContinue?\033[m " - read OK - if [[ "$OK" = "YES" ]] ; then - echo "" - echo "" - echo -e "\033[1;37m-----------\033[m" - echo "" - echo "" - echo -e " \033[32mRunning \033[1;37mREPAIR TABLES\033[m\033[32m on all tables of all databases..\033[m" - echo "" - else - fatal "Abort by user request - Answer as not 'YES'" - fi - else - usage "No Databses given!" - fi + DATABASE_NAME="" fi @@ -234,139 +227,270 @@ else fi fi - -[[ -z "$mysql_credential_args" ]] && mysql_credential_args="$DEFAULT_MYSQL_CREDENTIAL_ARGS" - -if [[ ${#mysql_credential_args_arr[@]} -eq 0 ]]; then - [[ -z "$mysql_credential_args" ]] && mysql_credential_args="$DEFAULT_MYSQL_CREDENTIAL_ARGS" - mysql_credential_args_arr="default:$mysql_credential_args" +if [[ -n "$mysql_credential_args" ]]; then + MYSQL_CREDENTIAL_ARGS="$mysql_credential_args" +else + MYSQL_CREDENTIAL_ARGS="$DEFAULT_MYSQL_CREDENTIAL_ARGS" fi +declare -i index_arr=0 + +# - Get MySQL Version +# - +if [[ ${#mysql_credential_args_arr[@]} -gt 0 ]] ; then + + echo "" + echo -e "\033[32m--\033[m" + echo "" + echo "Which installation contains the database to be repaired?" + echo "" + echo "" + + declare -a _tmp_arr=() + while [[ $index_arr -lt ${#mysql_credential_args_arr[@]} ]] ; do + + IFS=':' read -a _val_arr <<< "${mysql_credential_args_arr[$index_arr]}" + + mysql_version="${_val_arr[0]}" + mysql_credential_args="${_val_arr[1]}" + mysql_dist_string="$(mysql $mysql_credential_args -N -s -e "SELECT VERSION()" 2> /dev/null)" + if [[ "$mysql_dist_string" =~ MariaDB ]]; then + mysql_dist="MariaDB $mysql_version" + else + mysql_dist="MySQL/Percona $mysql_version" + fi + echo -e " [\033[33m$index_arr\033[m] \033[33m$mysql_dist\033[m" + _temp_arr[${index_arr}]="$mysql_credential_args" + #_temp_arr+=("$mysql_credential_args") + (( index_arr++ )) + done + + _OK=false + echo "" + echononl "Eingabe: " + while ! $_OK ; do + read _IN + if is_number "$_IN" && [[ -n ${_temp_arr[$_IN]} ]]; then + + MYSQL_CREDENTIAL_ARGS="${_temp_arr[$_IN]}" + _OK=true + else + echo "" + echo -e "\tFalsche Eingabe !" + echo "" + echononl "Eingabe: " + fi + done + +fi + +if $DATABASE_NAME_NEEDED ; then + echo "" + echo -e "\033[32m--\033[m" + echo "" + echo "Insert Database name which should be repaired.." + echo "" + echo -e " \033[33mLeave empty to repair tables of all databases\033[m" + echo "" + echononl "Database name: " + read DATABASE_NAME + #while [ "X$DATABASE_NAME" = "X" ] ; do + # echo -e "\n\t\033[33m\033[1mEingabe erforderlich.\033[m\n" + # echononl "Database name: " + # read DATABASE_NAME + #done +fi + +# - Get MySQL Version +# - +echo "" +echo -e "\033[32m--\033[m" +echo "" +echononl " Get MySQL Version" +_version="$(mysql $MYSQL_CREDENTIAL_ARGS -N -s -e "SELECT VERSION()" 2> $tmp_log_file)" +if [[ $? -ne 0 ]] ; then + echo_failed + fatal "$(cat $tmp_log_file)" +else + echo_ok +fi + +IFS='.' read -r -a version_arr <<< "$_version" +declare -i MAJOR_VERSION="${version_arr[0]}" +declare -i MINOR_VERSION="${version_arr[1]}" +_path_level="${version_arr[2]}" +declare -i PATCH_LEVEL="${_path_level%%-*}" + +## - Get current MySQL Distribution +## - +echononl " Get MySQL distribution .." +if [[ -z "$_version" ]]; then + echo_failed + fatal "No installed MySQL server or distribution found!" +elif [[ "$_version" =~ MariaDB ]]; then + MYSQL_CUR_DISTRIBUTION="MariaDB" +else + MYSQL_CUR_DISTRIBUTION="MySQL" +fi +echo_ok +echo "" +echo -e "\033[32m--\033[m" +echo "" + +echo "" +echo "" +echo -e "\033[32m\033[1m====================\033[m" +echo "Settings: Repair tables of MySQL Database '$DATABASE_NAME'" +echo -e "\033[32m\033[1m====================\033[m" +echo "" +echo " MySQL Distribution...........: $MYSQL_CUR_DISTRIBUTION" +echo " MySQL Version................: ${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_LEVEL}" +echo " MySQL Credentials............: $MYSQL_CREDENTIAL_ARGS" +echo "" +if [[ -n "$DATABASE_NAME" ]]; then + echo " Database name................: $DATABASE_NAME" +else + echo -e " Database name................: -- \033[033mall databases\033[m --" +fi +echo "" +echo "" + +echo -e -n "\033[1mContinue repairing tables with above settings? [y/n]:\033[m " +read OK +while [[ "X${OK}X" = "XX" ]] ; do + echo "" + echo -e -n "\033[1mContinue with above settings? [y/n]:\033[m " + read OK +done + +if [[ "${OK,,}" != 'yes' ]] && [[ "${OK,,}" != 'y' ]]; then + fatal "Abort by user request." +fi + + declare -i length_table_name declare -i number_blank_signd declare -i index_i -for _val in ${mysql_credential_args_arr[@]} ; do - _all_success=true +_all_success=true - IFS=':' read -a _val_arr <<< "${_val}" - mysql_version="${_val_arr[0]}" - mysql_credential_args="${_val_arr[1]}" +DATABASES="$(mysql $MYSQL_CREDENTIAL_ARGS -N -s -e "show databases")" - DATABASES="$($mysql $mysql_credential_args -N -s -e "show databases")" +if [[ -z "$DATABASE_NAME" ]] ; then - if [[ -z "$GIVEN_DATABASE" ]] ; then - - if $terminal ; then - echo "" - echo -e "[ \033[37m\033[1mMySQL $mysql_version\033[m ]: repair (and optimize) tables of databases at host '$(hostname -f)'." - fi - - ALL_DATABASES=true - else - found=false - for db in $DATABASES ; do - if [[ "$db" = "$GIVEN_DATABASE" ]]; then - DATABASES="$GIVEN_DATABASE" - found=true - fi - done - if ! $found ; then - continue - fi + if $terminal ; then + echo "" + echo -e " [ \033[37m\033[1m$MYSQL_CUR_DISTRIBUTION ${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_LEVEL}\033[m ]: repair (and optimize) tables of ALL databases at host '$(hostname -f)'." fi - length_table_name=0 - for db in $DATABASES ; do + ALL_DATABASES=true +else + found=false + for db in $DATABASES ; do + if [[ "$db" = "$DATABASE_NAME" ]]; then + DATABASES="$DATABASE_NAME" + found=true + break + fi + done + if ! $found ; then + warn "No Database '$DATABASE_NAME' found at $MYSQL_CUR_DISTRIBUTION ${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_LEVEL}" + clean_up 0 + fi +fi - [ "$db" = "information_schema" ] && continue - [ "$db" = "performance_schema" ] && continue - [ "$db" = "mysql" ] && continue - if $terminal ;then - echo "" - if [[ -n "$GIVEN_DATABASE" ]] ; then - echo -e " [$(date)] Repair (and optimize) tables in database '${db}'.." - else - echo -e " [ \033[37m\033[1mMySQL $mysql_version\033[m $(date) ] Repair (and optimize) tables in database '${db}'.." - fi - fi +length_table_name=0 +for db in $DATABASES ; do - TABLES="$($mysql $mysql_credential_args $db -N -s -e "show tables" 2> $tmp_log_file )" - if [[ $? -ne 0 ]]; then - _all_success=false - error "Getting tables of database '${db}' failed.\n $(cat "$tmp_log_file")" - error_messages_arr+=("Getting tables of database '${db}' failed.") - continue - fi + [ "$db" = "information_schema" ] && continue + [ "$db" = "performance_schema" ] && continue + [ "$db" = "mysql" ] && continue - for table in $TABLES ; do + if $terminal ;then + echo "" + if [[ -n "$DATABASE_NAME" ]] ; then + echo -e " [$(date)] Repair (and optimize) tables in database '${db}'.." + else + echo -e " [ \033[37m\033[1m$MYSQL_CUR_DISTRIBUTION ${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_LEVEL}\033[m $(date) ] Repair (and optimize) tables in database '${db}'.." + fi + fi - # - Ommit InnoDB tables - # - - _engine="$($mysql $mysql_credential_args -N -s -e "SELECT ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA = '$db' AND TABLE_NAME = '$table'")" - if [[ "${_engine,,}" = 'innodb' ]] ; then - echo -e " [$(date)] Ommit table '$table' - The storage engine (InnoDB) doesn't support repair" - continue - fi + TABLES="$($mysql $MYSQL_CREDENTIAL_ARGS $db -N -s -e "show tables" 2> $tmp_log_file )" + if [[ $? -ne 0 ]]; then + _all_success=false + error "Getting tables of database '${db}' failed.\n $(cat "$tmp_log_file")" + error_messages_arr+=("Getting tables of database '${db}' failed.") + continue + fi - if $terminal ; then - blank_signs="" - if [[ $length_table_name -gt ${#table} ]]; then - number_blank_sign=$(expr $length_table_name - ${#table}) - index_i=0 - while [[ $index_i -lt $number_blank_sign ]] ; do - blank_signs="$blank_signs " - (( index_i++ )) - done - echo -en "\033[1G" - fi - echo -en "\033[1G \033[32mRepair table \033[1m$table\033[m$blank_signs\033[1G" - fi - length_table_name=${#table} + for table in $TABLES ; do - $mysql $mysql_credential_args $db -N -s -e "REPAIR TABLE \`$table\`" > $tmp_log_file 2>&1 + # - Ommit InnoDB tables + # - + _engine="$($mysql $MYSQL_CREDENTIAL_ARGS -N -s -e "SELECT ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA = '$db' AND TABLE_NAME = '$table'")" + if [[ "${_engine,,}" = 'innodb' ]] ; then + echo -e " [$(date)] Ommit table '$table' - The storage engine (InnoDB) doesn't support repair" + continue + fi - if [[ $? -ne 0 ]]; then + if $terminal ; then + blank_signs="" + if [[ $length_table_name -gt ${#table} ]]; then + number_blank_sign=$(expr $length_table_name - ${#table}) + index_i=0 + while [[ $index_i -lt $number_blank_sign ]] ; do + blank_signs="$blank_signs " + (( index_i++ )) + done + echo -en "\033[1G" + fi + echo -en "\033[1G \033[32mRepair table \033[1m$table\033[m$blank_signs\033[1G" + fi + length_table_name=${#table} - _all_success=false - error "Repairing table '$table' failed.\n$(cat "$tmp_log_file")" - error_messages_arr+=("MySQL $mysql_version: Error while repairing table '${table}' of database '$db'.") + $mysql $MYSQL_CREDENTIAL_ARGS $db -N -s -e "REPAIR TABLE \`$table\`" > $tmp_log_file 2>&1 - else + if [[ $? -ne 0 ]]; then - $mysql $mysql_credential_args $db -N -s -e "OPTIMIZE TABLE \`$table\`" > $tmp_log_file 2>&1 + _all_success=false + error "Repairing table '$table' failed.\n$(cat "$tmp_log_file")" + error_messages_arr+=("$MYSQL_CUR_DISTRIBUTION ${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_LEVEL}: Error while repairing table '${table}' of database '$db'.") - if [[ $? -ne 0 ]]; then - error "Reoptimizing table \"${table}\" of database \"$db\" failed.\n$(cat "$tmp_log_file")" - error_messages_arr+=("MySQL $mysql_version: Error while (re-)optimizing table '${table}' of database '$db'.") - fi - fi + else - done + $mysql $MYSQL_CREDENTIAL_ARGS $db -N -s -e "OPTIMIZE TABLE \`$table\`" > $tmp_log_file 2>&1 - if $terminal ;then - echo -en "\033[1G [$(date)] End repairing tables of database '${db}'.." - echo - fi + if [[ $? -ne 0 ]]; then + error "Reoptimizing table \"${table}\" of database \"$db\" failed.\n$(cat "$tmp_log_file")" + error_messages_arr+=("$MYSQL_CUR_DISTRIBUTION ${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_LEVEL}: Error while (re-)optimizing table '${table}' of database '$db'.") + fi + fi - done + done - if $_all_success ; then - if $ALL_DATABASES ; then - info_messages_arr+=("MySQL $mysql_version: Repairing MySQL tables of all databases was successful.") - else - info_messages_arr+=("MySQL $mysql_version: Repairing MySQL tables of database '${db}' was successful.") - fi - fi + if $terminal ;then + echo -en "\033[1G [$(date)] End repairing tables of database '${db}'.." + echo + fi - if $terminal && $ALL_DATABASES ; then - echo "" - echo -e "[ \033[37m\033[1mMySQL $mysql_version\033[m ]: Finished repairing MySQL databases at host $(hostname -f)." - echo "" - fi done +if $_all_success ; then + if $ALL_DATABASES ; then + info_messages_arr+=("$MYSQL_CUR_DISTRIBUTION ${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_LEVEL}: Repairing MySQL tables of all databases was successful.") + else + info_messages_arr+=("$MYSQL_CUR_DISTRIBUTION ${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_LEVEL}: Repairing MySQL tables of database '${db}' was successful.") + fi +fi + +if $terminal && $ALL_DATABASES ; then + echo "" + echo -e " [ \033[37m\033[1m$MYSQL_CUR_DISTRIBUTION ${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_LEVEL}\033[m ]: Finished repairing MySQL databases at host $(hostname -f)." + echo "" +fi + + if [[ ${#info_messages_arr[@]} -gt 0 ]]; then for msg in "${info_messages_arr[@]}" ; do if $terminal ; then