#! /bin/bash # function library for various tasks (not applicable to other libraries mostly) # v. 1.2.9 # Function list: # k_kolmisoft_logo() - function prints kolmisoft logo # k_start() - function to start the script, add $@ to pass arguments # k_exit() - function to end the script with message and proper exit code # report - function prints text with colored status # k_delay() - functions prints . (dot) every second. Useful to pause but show that script did not stuck. Usage example: k_delay 10 "Custom text" # k_download_packet() - function downloads packet from www.kolmisoft.com/packets. Add 'quiet' as 2nd parameter for silence. # k_dump_db_table() - function dumps DB table to gzip # $1 - table to dump # $2 - backup dir (defaults to /usr/local/m2|mor/backups) #3 CONFIRM # k_symlink_create() - functions creates symlink if it's not present or recreates it if it's broken # k_debug() - function waits for ENTER if $DEBUG == 1 . /usr/src/k_framework/data_get.sh # Function naming rules # k__ where either object or action are not mandatory (only object or only action is necessary, could be both also) # function prints kolmisoft logo # http://patorjk.com/software/taag/#p=display&f=ANSI%20Shadow&t=KOLMISOFT k_kolmisoft_logo(){ echo echo " ██╗ ██╗ ██████╗ ██╗ ███╗ ███╗██╗███████╗ ██████╗ ███████╗████████╗" echo " ██║ ██╔╝██╔═══██╗██║ ████╗ ████║██║██╔════╝██╔═══██╗██╔════╝╚══██╔══╝" echo " █████╔╝ ██║ ██║██║ ██╔████╔██║██║███████╗██║ ██║█████╗ ██║" echo " ██╔═██╗ ██║ ██║██║ ██║╚██╔╝██║██║╚════██║██║ ██║██╔══╝ ██║" echo " ██║ ██╗╚██████╔╝███████╗██║ ╚═╝ ██║██║███████║╚██████╔╝██║ ██║" echo " ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝" echo " ╦ ╦╔═╗ ╔╦╗╔═╗╦╔═╔═╗ ╔═╗╔═╗╔═╗╔╦╗╔═╗╦ ╦╦╔╦╗╔═╗╦ ╦╔═╗╔═╗" echo " ║║║║╣ ║║║╠═╣╠╩╗║╣ ╚═╗║ ║╠╣ ║ ╚═╗║║║║ ║ ║ ╠═╣║╣ ╚═╗" echo " ╚╩╝╚═╝ ╩ ╩╩ ╩╩ ╩╚═╝ ╚═╝╚═╝╚ ╩ ╚═╝╚╩╝╩ ╩ ╚═╝╩ ╩╚═╝╚═╝" echo } # function to start the script, add $@ to pass arguments k_start() { if [[ $SCRIPT_NAME == "" ]]; then report "SCRIPT_NAME variable empty" 1 k_exit 1 fi if [[ $VERSION == "" ]]; then report "VERSION variable empty" 1 k_exit 1 fi for arg in "$@" do if [ "$arg" == "-v" ]; then echo $VERSION exit fi done EXIT_CODE=0 echo -e "\\t\\tStarting \E[97m$SCRIPT_NAME\E[34m\033[0m script v$VERSION"; } # function to end the script with message and proper exit code k_exit() { local param=$1 local happy=$2 local sad=$3 if [[ $param == "" ]]; then param=1; fi if [[ $param == 0 ]]; then # report "Script $SCRIPT_NAME completed. $happy" 0 echo -e "\E[32m OK \E[32m\033[0m\\t\\tScript \E[97m$SCRIPT_NAME\E[34m\033[0m completed. $happy"; else if [ $param == 1 ]; then report "Script \E[97m$SCRIPT_NAME\E[34m\033[0m FAILED. $sad" 1 else report "Script \E[97m$SCRIPT_NAME\E[34m\033[0m did not end properly... $sad" $param fi fi if [ "$TEST" != "1" ]; then exit $param fi } # function prints text with colored status # naming left for backwards compatibility report() { # Author: Mindaugas Mardosas # This function is used for displaying output with color status. # Usage: # report "some text" [0-5] # # The function returns the same parameter it received. # # This function accepts these arguments: # $1 - text to display # $2 - send status manually # $2 or $3 - "FAILED" #causes not to print [OK] blabblabla. In other words if the functions has to report OK - it will print nothing # # Internal variable that can be used outside: # ALL_OK - this variable can be used to track if all tests from that group went ok. Read more about this variable usage in Example 5 # returns/accepts these codes: # # 0 - ok # 1 - failed # 2 - warning # 3 - notice # 4 - fixed # 5 - overwritten # 6 - RED TEXT # 7 - echo text to screen. Text with this status will not be printed when -compact or -c settings will be used when running the testing framework # # Usage examples: # Example 1: # report "some output" 1 #would report "FAILED" and return 1 # # would produce similar output and return 1: # FAILED some output # # Example 2: # report "some output" 0 #would report "OK" and return 0 # # would produce similar output and return 0: # OK some output # # Example 3 (command combine): # Here is a simple command that returns 1 that states failure and 0 when a match is found (success): # [root@localhost ~]# grep erdtfyguhjiok /etc/passwd #grep will not find anything and return 1 # [root@localhost ~]# echo $? # 1 # [root@localhost ~]# # When using such simple commands or functions which return 0 on OK and 1 on failure you can leave the second parameter not filled: # grep erdtfyguhjiok /etc/passwd # report "Grep command status" # # would produce similar output and this time return 1: # FAILED Grep command status # # Example 4: # report "some output" 0 FAILED # # would produce no output at all and return 0: # # Example 5: # Now we will use ALL_OK variable to display some summary result about 3 tests: # ALL_OK=0 #resetting the variable # report "some output" 0 FAILED # report "some output" 0 FAILED # report "some output" 0 FAILED # # if [ "$ALL_OK" == "0" ]; then # echo "All 3 tests passed successfully" # else # echo "One or more tests failed" # fi # #------------------ if [ "$2" != "" ]; then result=$2; else # 2nd parameter is not available - use last command status result=$?; fi #------------------ if [ -f "/tmp/.mor_global_test-fix_framework_variables" ]; then #including global test-fix framework variables if any of them are available source /tmp/.mor_global_test-fix_framework_variables fi if [ "$result" == "0" ]; then if [ "$3" == "FAILED" ] ; then return 0; fi #causes not to print [OK] blabblabla if [ "$COMPACT_OUTPUT" != "COMPACT" ]; then #if compact option was passed - this message will not be printed echo -e "\E[32m OK \E[32m\033[0m\\t\t$1"; fi return 0; else ALL_OK=1 #some checks failed if [ "$result" == "1" ]; then echo -e "\E[91m FAILED \E[31m\033[0m\\t$1"; return 1; elif [ "$result" == "2" ]; then echo -e "\E[93m WARNING! \E[33m\033[0m\\t$1"; return 2; elif [ "$result" == "3" ]; then echo -e "\E[94m NOTICE \E[36m\033[0m\\t$1"; return 3; elif [ "$result" == "4" ]; then echo -e "\E[96m FIXED \E[34m\033[0m\\t\t$1"; return 4; elif [ "$result" == "5" ]; then echo -e "\E[34m Overwritten \E[34m\033[0m\\t$1"; return 5; elif [ "$result" == "6" ]; then #echo -e "\n\n\n\E[5m\E[31m$1\E[31m\033[0m\E[25m\\n\n"; echo -e "\E[91m CRITICAL \\t$1\E[34m\033[0m"; return 6; elif [ "$result" == "7" ]; then if [ "$COMPACT_OUTPUT" != "COMPACT" ]; then #if compact option was passed - this message will not be printed echo -e "\\t\\t$1"; fi return 7; elif [ "$result" == "8" ]; then echo -e "\\t\\t\E[97m$1\E[34m\033[0m"; return 8; elif [[ "$result" == "9" || "$result" == "fix" ]]; then echo -e "\E[33m FIX \\t\t$1\E[34m\033[0m"; return; fi fi } # functions prints . (dot) every second. Useful to pause but show that script did not stuck. Usage example: k_delay 10 # to change the text, enter as a 2nd param, example: k_delay 10 "Testing" k_delay() { if [[ $2 != "" ]]; then echo -n " $2 [${1}s] " else echo -n " Delay for $1 seconds " fi for (( c=1; c<=$1; c++ )); do echo -n "." sleep 1 done echo -ne "\r\033[2K" } # function downloads packet from www.kolmisoft.com/packets. Add 'quiet' as 2nd parameter for silence. k_download_packet() { cd /usr/src/ if [ -r $1 ]; then report "$1 is already downloaded" 3 else k_config_details report "Downloading $1" 3 if [[ $2 == "quiet" ]]; then wget --no-check-certificate -q "http://packets.kolmisoft.com/packets/$1" > /dev/null 2>&1 else wget --no-check-certificate "http://packets.kolmisoft.com/packets/$1" fi if [ $? != 0 ]; then echo -n `date` >> /var/log/$SYSTEM_CONFIG_DIR/packet_download.log echo -e " $1 failed to download\n#==================" >> /var/log/$SYSTEM_CONFIG_DIR/packet_download.log fi fi } # functions creates symlink if it's not present or recreates it if it's broken k_symlink_create() { local src=$1 local dst=$2 if [[ $src == "" || $dst == "" ]]; then report "bad arguments" 1 return fi if [[ ! -r $src ]]; then report "$src does not exist" 1 return fi if [ -L ${dst} ] ; then if [ -e ${dst} ] ; then report "Symlink $src $dst already present" 3 else report "Symlink $src $dst broken, recreating" 3 rm -fr $dst ln -s $src $dst fi elif [ -e ${dst} ] ; then report "$dst is not a link" 1 else ln -s $src $dst fi } # function dumps DB table to gzip # $1 - table to dump # $2 - backup dir (defaults to /usr/local/m2|mor/backups) # #3 - if 3rd parameter CONFIRM, will ask for permission for backup k_dump_db_table() { if [[ -z $1 ]]; then report "k_dump_db_table needs parameters" 1 return 1; fi k_config_details local table_name="$1" local backup_dir="/usr/local/$SYSTEM_CONFIG_DIR/backups" local current_date="$(date +"%Y%m%d_%H%M%S")" local backup_path="" local confirm_arg="$3" local ARC="pigz" # pigz faster than gzip ~15%. Bottleneck is mysqldump. pigz --fast faster than gzip ~20-25%, takes +25% more space if [ ! -f /usr/bin/pigz ]; then report "pigz not present, will install" 2 yum -y install pigz if [ ! -f /usr/bin/pigz ]; then report "Failed to install pigz, will use gzip" 2 ARC="gzip" fi fi if [[ ! -z $2 && -d $2 ]]; then backup_dir="$2" fi backup_path=$(printf "%s/table_backup_%s_%s.sql.gz" "$backup_dir" "$table_name" "$current_date") if [[ -f "$backup_path" ]]; then report "DB backup $backup_path already exists. Rename existing backup if would like another one would be created" 3 return 3 fi local table_takes_space=$(MYSQL_PWD=$DB_PASSWORD /usr/bin/mysql -h "$DB_HOST" -u $DB_USERNAME $P_OPT "$DB_NAME" --disable-column-names -B -e "SELECT ROUND(data_length/1024/1024) as SIZE from information_schema.tables where table_schema = '$DB_NAME' and table_name = '$table_name'") local free_backup_space=$(df -P $backup_dir | (read; awk '{print $4}')) free_backup_space=$(($free_backup_space / 1024)) # 1515 MB / min with 128GB calls table test approx_time=$(($table_takes_space / 1515)) # approx commpression ratio with --fast: 4.5 approx_space=$(($table_takes_space * 10 / 45)) report "Data size in the db (MB): $table_takes_space" 3 report "Free space in backup dir (MB): $free_backup_space" 3 report "Approximate archive size (MB): $approx_space" 3 report "Approximate work time : $approx_time min" 3 if (( free_backup_space < tables_takes_sace/4 )); then report "We estimate that there is is not enough free space to make backup in $backup_dir" 3 report "Backup for table [$table_name] will not be created" 3 return 1 fi if [[ $table_takes_space -gt 10000 ]]; then confirm_arg="CONFIRM" fi if [ "$confirm_arg" == "CONFIRM" ]; then echo "Execute [$table_name] backup procedure? (y/n/s - skip)" read -t 60 EXECUTE_PROCEDURE if [ "$EXECUTE_PROCEDURE" != "y" ]; then if [ "$EXECUTE_PROCEDURE" != "s" ]; then report "Backup procedure was cancelled" 3 return 1 else report "Backup procedure was skipped" 3 return 0 fi fi fi start_time="$(date +"%Y-%m-%d %H:%M:%S")" report "$start_time - Dumping and compressing table [$table_name] using [$ARC] to $backup_path" 3 MYSQL_PWD=$DB_PASSWORD mysqldump --single-transaction -h "$DB_HOST" -u "$DB_USERNAME" $P_OPT "$DB_NAME" "$table_name" | $ARC --fast > "$backup_path" end_time="$(date +"%Y-%m-%d %H:%M:%S")" report "$end_time - finished" 3 if [[ ! -f "$backup_path" ]]; then report "Failed to dump and compress table [$table_name]" 1 return 1 else FILESIZE=$(stat -c%s "$backup_path") FILESIZE_MB=$(($FILESIZE / 1024 / 1024)) report "Table [$table_name] backup prepared successfully" 0 report "File size: $FILESIZE_MB MB" 3 fi return 0 } # " function waits for ENTER if $DEBUG == 1 k_debug() { if [[ $DEBUG = 1 ]]; then report "Press ENTER to continue" 3 read fi }