#!/usr/bin/env bash working_dir="$(dirname $(realpath $0))" conf_file="${working_dir}/conf/mysql_credetials.conf" tmp_log_file="$(mktemp)" # ------------- # - Variable settings # ------------- DEFAULT_MYSQL_CREDENTIAL_ARGS="--login-path=local" ALL_DATABASES=false # ------------- # --- Some functions # ------------- usage() { [[ -n "$1" ]] && error "$1" [[ $terminal ]] && echo -e " \033[1mUsage:\033[m $(basename $0) \033[1mDescription\033[m Script repairs (and reorganizes) all tables of the given databases by executing MySQL command 'REPAIR TABLE'. If this was successfully, also 'OPTIMIZE TABLE' command will be triggered. \033[1mOptions\033[m No Options available \033[1mFiles\033[m $conf_file: Configuration file " clean_up 1 } clean_up() { # Perform program exit housekeeping rm -f $tmp_log_file exit $1 } echononl(){ if $terminal ; then echo X\\c > /tmp/shprompt$$ if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then echo -e -n "$*\\c" 1>&2 else echo -e -n "$*" 1>&2 fi rm /tmp/shprompt$$ fi } fatal(){ echo "" if $terminal ; then if [[ -n "$*" ]] ; then echo -e " [ \033[31m\033[1mFatal\033[m ]: $*" echo "" echo -e " \033[31m\033[1mScript will be interrupted.\033[m\033[m" else echo -e " \033[31m\033[1mFatal error\033[m: \033[1mScript will be interrupted.\033[m" fi else if [[ -n "$*" ]] ; then echo " [ Fatal ]: $*" echo "" echo " Script was terminated.." else echo " Fatal error: Script was terminated.." fi fi echo "" clean_up 1 } error(){ echo "" if $terminal ; then echo -e " [ \033[31m\033[1mError\033[m ]: $*" else echo " [ Error ]: $*" fi echo "" } warn (){ if $terminal ; then echo "" echo -e " [ \033[33m\033[1mWarning\033[m ]: $*" echo "" else echo " [ Warning ]: $*" fi } info (){ if $terminal ; then echo "" echo -e " [ \033[32m\033[1mInfo\033[m ]: $*" echo "" else echo " [ Info ]: $*" fi } echo_ok() { if $terminal ; then echo -e "\033[80G[ \033[32mok\033[m ]" fi } echo_failed(){ if $terminal ; then echo -e "\033[80G[ \033[1;31mfailed\033[m ]" fi } echo_skipped() { if $terminal ; then echo -e "\033[80G[ \033[37mskipped\033[m ]" fi } trim() { local var="$*" var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters echo -n "$var" } trap clean_up SIGHUP SIGINT SIGTERM # - Is this script running on terminal ? # - if [[ -t 1 ]] ; then terminal=true else terminal=false fi mysql=`which mysql` if [ -z "$mysql" ]; then if [ -x "/usr/local/mysql/bin/mysql" ]; then mysql=/usr/local/mysql/bin/mysql else fatal "No binary 'mysql' found!" fi fi # - Print help? # - if [[ "$(trim $*)" = "-h" ]] || [[ "$(trim $*)" = "--help" ]] ; then usage fi # ------------- # - Get Database from commandline # ------------- if [[ -n "$1" ]] ; then DATABASES="$1" else 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 fi # ------------- # - Load Settings from configuration file # ------------- if $terminal ; then echo "" fi echononl " Loading configuration settings from $(basename ${conf_file}).." if [[ -f "$conf_file" ]]; then source "$conf_file" > $tmp_log_file 2>&1 if [[ $? -eq 0 ]]; then echo_ok else echo_failed fatal "$(cat $tmp_log_file)" fi else echo_skipped if $terminal ;then warn "No Configuration File found. Loading defaults.." 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" 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 IFS=':' read -a _val_arr <<< "${_val}" mysql_version="${_val_arr[0]}" mysql_credential_args="${_val_arr[1]}" if [[ -z "$DATABASES" ]] ; 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 DATABASES="$($mysql $mysql_credential_args -N -s -e "show databases")" ALL_DATABASES=true fi length_table_name=0 for db in $DATABASES ; do [ "$db" = "information_schema" ] && continue [ "$db" = "performance_schema" ] && continue [ "$db" = "mysql" ] && continue if $terminal ;then echo "" echo -e " [$(date)] Repair (and optimize) tables in database '${db}'.." 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 for table in $TABLES ; do # - 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 $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} $mysql $mysql_credential_args $db -N -s -e "REPAIR TABLE \`$table\`" > $tmp_log_file 2>&1 if [[ $? -ne 0 ]]; then _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'.") else $mysql $mysql_credential_args $db -N -s -e "OPTIMIZE TABLE \`$table\`" > $tmp_log_file 2>&1 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 done if $terminal ;then echo -en "\033[1G [$(date)] End repairing tables of database '${db}'.." echo fi 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 && $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 [[ ${#info_messages_arr[@]} -gt 0 ]]; then for msg in "${info_messages_arr[@]}" ; do if $terminal ; then info "$msg" fi done fi if [[ ${#error_messages_arr[@]} -gt 0 ]]; then for msg in "${error_messages_arr[@]}" ; do if $terminal ; then error "$msg" fi done fi clean_up 0