1#!/bin/sh -u 2# 3# -u: nounset (enable: set -u | disable: set +u) 4# -e: errexit 5# -r: restricted 6# 7# 8# VARIABLE CONVENTIONS 9# 10# 1. Function variables 11# ---------------------- 12# * Lowercase 13# * Prefixed with _ 14# Example: _tmp, _dir, _len 15# 16# 2. Config file variables 17# ------------------------ 18# * Uppercase 19# * No prefix 20# Example: MYSQL_OPTS 21# 22# 3. Default values for config file variables 23# ------------------------------------------- 24# * Uppercase 25# * Prefixed with _DEFAULT_ 26# * Same name as config file variables 27# Example: _DEFAULT_CONFIG_FILE 28# 29# 4. Global program variables 30# ------------------------------------------- 31# TODO: Also think about other schema, so I don't mix 32# them up with vars from the config. 33# * Uppercase 34# * Prefixed with identifier, such as: MDS_[SECTION]_, DB_[SECTION]_ 35# Example: MDS_INFO_NAME, DB_CNT_FAILED 36# 37# 5. Variables within loops / Temporary variables 38# ------------------------------------------- 39# * Uppercase 40# * Prefixed with _TMP 41# Example: _TMP_RESULT <-- TODO: Fix this 42 43 44# 45# Normalize 46# Don't screw with numbers, sorting, date etc 47# 48LANG=C 49LC_ALL=C 50 51 52 53#################################################################################################### 54#################################################################################################### 55## 56## GLOBAL VARIABLES 57## 58#################################################################################################### 59#################################################################################################### 60 61 62################################################################################ 63# 64# VERSION / CREDITS 65# 66################################################################################ 67 68# 69# Some of this data is also written to the nagios logfile 70# in order to be able to check against latest/desired mysqldump-secure version. 71# 72# TODO: Prefix with MDS_ 73INFO_NAME="mysqldump-secure" 74INFO_AUTHOR="Patrick Plocke <patrick@plocke.de>" 75INFO_GPGKEY="0x28BF179F" 76INFO_LICENSE="MIT" 77INFO_URL="http://mysqldump-secure.org" 78INFO_REPO="https://github.com/cytopia/mysqldump-secure" 79INFO_DATE="2016-08-18" 80INFO_VERSION="0.16.3" 81 82 83 84################################################################################ 85# 86# AUTO-GENERATED 87# 88################################################################################ 89 90# The following are auto-generated variables by the installer. 91# to determine where the script and its config files are installed. 92_PREFIX_ETC="" 93_PREFIX_LOG="" 94_PREFIX_VAR="" 95 96 97 98 99################################################################################ 100# 101# EXIT CODES 102# 103################################################################################ 104 105# Everything went fine. 106# No errors and no warnings. 107EXIT_OK=0 108 109# The database dump was successful, but some other 110# warnings occured. 111# E.g.: tmpreaper/tmpwatch could not delete files, etc 112EXIT_WARNING=1 113 114# The database dump was successful, but some other 115# errors occured. 116# E.g.: Directories could not be created, etc 117EXIT_ERROR=2 118 119# The database dump had errors. 120# E.g.: File already existed, wrong mysqldump options, wrong compression options, etc 121EXIT_FAIL=3 122 123# The program terminated before it could do backups 124# E.g.: No database connection, wrong config settings, etc 125EXIT_ABORT=4 126 127 128# Internal program error. 129# This should never happen, but when it does 130# the code is wrong 131EXIT_INT_ERR=5 132 133 134 135 136################################################################################ 137# 138# WARNING, ERROR, FAIL COUNTER 139# 140################################################################################ 141 142# 143# How many warnings occured 144# 145MDS_WARNING_COUNT=0 146 147# 148# How many errors occured 149# 150MDS_ERROR_COUNT=0 151 152 153# 154# How many failed database dumps occured 155# 156MDS_FAIL_COUNT=0 157 158 159 160 161################################################################################ 162# 163# DEFAULT VARIABLES 164# 165################################################################################ 166 167# 168# Do not djust the following default variables! 169# They can be overwritten inside mysqldump-secure.conf 170# or via command line arguments 171# 172 173# Default Configuration Path/Name 174_DEFAULT_CONFIG_FILE="${_PREFIX_ETC}/etc/mysqldump-secure.conf" 175_DEFAULT_CONFIG_CHMOD="0400" 176 177# Default output Variables 178_DEFAULT_DUMP_DIR="${_PREFIX_VAR}/var/mysqldump-secure" 179_DEFAULT_DUMP_DIR_CHMOD="0700" 180 181_DEFAULT_DUMP_FILE_PRE="$(date '+%Y-%m-%d')_$(date '+%H-%M')__" 182_DEFAULT_DUMP_FILE_CHMOD="0400" 183 184 185# MySQL defaults 186_DEFAULT_MYSQL_CNF_CHMOD="0400" 187 188# Default minimum size (in MB) required to enable `--quick` 189_DEFAULT_MYSQL_OPTS_QUICK_MIN_SIZE=200 190 191# Default OpenSSL Variables 192_DEFAULT_OPENSSL_ALGO_ARG="-aes256" 193 194# Logging defaults 195_DEFAULT_LOG_CHMOD="0600" 196_DEFAULT_LOG_FILE="${_PREFIX_LOG}/var/log/mysqldump-secure.log" 197 198# Default nagios variables 199_DEFAULT_NAGIOS_LOG_CHMOD="0644" 200 201# Default system temp directory 202_DEFAULT_TMP_DIR="/tmp" 203 204 205 206################################################################################ 207# 208# MYSQL VARIABLES 209# 210################################################################################ 211 212 213# These command line arguments are considered insecure and can lead 214# to compromising your data 215MDS_MYSQL_EVIL_OPTS="--password -p --port -P --user -u --host -h --socket -s" 216 217# Do not allow to read any other MySQL configuration file 218# than the one specified in the configuration. 219MDS_MYSQL_BAD_OPTS="--no-defaults --defaults-extra-file --defaults-file" 220# All SSL Options are done via configuration 221MDS_MYSQL_BAD_OPTS="${MDS_MYSQL_BAD_OPTS} --ssl --ssl-ca --ssl-cert --ssl-key" 222# All Transaction Options (Consistency) are done via configuration 223MDS_MYSQL_BAD_OPTS="${MDS_MYSQL_BAD_OPTS} --single-transaction --lock-tables --skip-lock-tables" 224# Handled conditionally 225MDS_MYSQL_BAD_OPTS="${MDS_MYSQL_BAD_OPTS} --quick -q --skip-quick" 226 227 228 229################################################################################ 230# 231# TERMINAL COLORS 232# 233################################################################################ 234 235# If having a tty (console) use colors 236if [ -t 1 ]; then 237 CLR_FATAL="\033[0;31m" # Red 238 CLR_ERROR="\033[0;31m" # Red 239 CLR_WARNING="\033[0;33m" # Yellow 240 CLR_INFO="" 241 CLR_OK="\033[0;32m" # Green 242 CLR_DEBUG="\033[0;37m" # Gray 243 CLR_TRACE="\033[0;37m" # Gray 244 CLR_RESET="\033[m" # Normal 245# Dump terminal (e.g.: via cron) 246else 247 CLR_FATAL="" 248 CLR_ERROR="" 249 CLR_WARNING="" 250 CLR_INFO="" 251 CLR_OK="" 252 CLR_DEBUG="" 253 CLR_TRACE="" 254 CLR_RESET="" 255fi 256 257 258 259 260 261#################################################################################################### 262#################################################################################################### 263## 264## G L O B A L F U N C T I O N S 265## 266#################################################################################################### 267#################################################################################################### 268 269 270# 271# Naming convention: 272# ------------------ 273# Functions starting with '_name' are considered private and should only 274# be called from within other functions. 275# 276 277 278 279################################################################################ 280# 281# ABORT 282# 283################################################################################ 284 285# This function is used to abort 286# the whole script if internal errors occured. 287# This function should never be called. 288# If this function is called, the programmer screwed up. 289# 290# @param string Calling function name (for reference) 291# @param string Affected variable name (for reference) 292# @param string Affected variable value (for reference) 293# @output string Error message 294# @exit integer This function aborts with exit code 295_abort_on_internal_error() { 296 _func="${1}" 297 _var="${2}" 298 _val="${3}" 299 300 echo "Unhandled exception in: ${_func}" 1>&2 301 echo "Invalid value for ${_var}: '${_val}'" 1>&2 302 echo "Please report this error on github: ${INFO_REPO}" 1>&2 303 echo "The programmer fucked up" 1>&2 304 echo "Good bye" 1>&2 305 306 exit ${EXIT_INT_ERR} 307} 308 309 310 311################################################################################ 312# 313# L O G G I N G F U N C T I O N S 314# 315################################################################################ 316 317 318############################################################ 319# Private Logger Helper 320############################################################ 321 322 323# Get the severity prefix for stdout/stderr and logging 324# 325# @param string Severity 326# @output string Formatted level 327# @return integer 0: success, 1: unknown level 328_get_severity_level_prefix() { 329 _lvl="${1}" 330 331 case "${_lvl}" in 332 trace) 333 echo "[TRACE]" 334 return 0 335 ;; 336 debug) 337 echo "[DEBUG]" 338 return 0 339 ;; 340 info) 341 echo "[INFO] " 342 return 0 343 ;; 344 ok) 345 echo "[OK] " 346 return 0 347 ;; 348 warn) 349 echo "[WARN] " 350 return 0 351 ;; 352 err) 353 echo "[ERR] " 354 return 0 355 ;; 356 fatal) 357 echo "[FATAL]" 358 return 0 359 ;; 360 *) 361 echo "[UNDEF]" 362 return 1 363 ;; 364 esac 365} 366 367 368# Get the severity color based on error level 369# 370# @param string Severity 371# @output string Color code 372# @return integer 0: success, 1: unknown level 373_get_severity_color_prefix() { 374 _lvl="${1}" 375 376 case "${_lvl}" in 377 trace) 378 echo "${CLR_TRACE}" 379 return 0 380 ;; 381 debug) 382 echo "${CLR_DEBUG}" 383 return 0 384 ;; 385 info) 386 echo "${CLR_INFO}" 387 return 0 388 ;; 389 ok) 390 echo "${CLR_OK}" 391 return 0 392 ;; 393 warn) 394 echo "${CLR_WARNING}" 395 return 0 396 ;; 397 err) 398 echo "${CLR_ERROR}" 399 return 0 400 ;; 401 fatal) 402 echo "${CLR_FATAL}" 403 return 0 404 ;; 405 *) 406 echo "" 407 return 1 408 ;; 409 esac 410} 411 412 413# 414# Output (single or multi-line) text to stdout, stderr or file 415# (Console Out Recursive: _cout) 416# 417# @param string Where to output: 'stdout', 'stderr' or file 418# @param string Line Prefix (e.g.: date or color) 419# @param string Multi/single line message to outout 420# @param string Line Suffix (e.g.: color resetter) 421# @return integer Success 422_coutr() { 423 _target="${1}" 424 _prefix="${2}" 425 _string="${3}" 426 _suffix="${4}" 427 428 if [ "${_target}" = "stderr" ]; then 429 IFS=' 430 ' 431 for _line in ${_string}; do 432 printf "${_prefix}%s${_suffix}\n" "${_line}" 1>&2 # stdout -> stderr 433 done 434 unset IFS 435 return 0 436 elif [ "${_target}" = "stdout" ]; then 437 IFS=' 438 ' 439 for _line in ${_string}; do 440 printf "${_prefix}%s${_suffix}\n" "${_line}" # stdout 441 done 442 unset IFS 443 return 0 444 elif [ -f "${_target}" ]; then 445 IFS=' 446 ' 447 for _line in ${_string}; do 448 printf "${_prefix}%s${_suffix}\n" "${_line}" >> "${_target}" # file 449 done 450 unset IFS 451 return 0 452 fi 453 454 return 1 455} 456 457 458# 459# Output single line to stdout, stderr or file. 460# (Console Out Inline: _couti) 461# 462# Make sure to take care about trailing newlines inside $_string 463# 464# @param string Where to output: 'stdout', 'stderr' or file 465# @param string Line Prefix (e.g.: date or color) 466# @param string Single line message to outout 467# @param string Line Suffix (e.g.: color resetter) 468# @return integer Success 469_couti() { 470 _target="${1}" 471 _prefix="${2}" 472 _string="${3}" 473 _suffix="${4}" 474 475 if [ "${_target}" = "stderr" ]; then 476 printf "${_prefix}${_string}${_suffix}%s" "" 1>&2 # stdout -> stderr 477 return 0 478 elif [ "${_target}" = "stdout" ]; then 479 printf "${_prefix}${_string}${_suffix}%s" "" # stdout 480 return 0 481 elif [ -f "${_target}" ]; then 482 printf "${_prefix}${_string}${_suffix}%s" "" >> "${_target}" # file 483 return 0 484 fi 485 486 return 1 487} 488 489 490 491############################################################ 492# Public Logger functions 493############################################################ 494 495# 496# Single- multi-line output to stdout/stderr and/or logfile. 497# 498# @public 499# 500# @param string _lvl Assigned log level: "trace", "debug", "info", "warn" or "err" "fatal" 501# Can also be a combination separated with '|' for an extra prefix. 502# E.g.: "err|(RUN)" 503# @param string _msg Message (single-line or multiline) 504# @param integer _ver (0|1|2|3) Current set verbosity level (0:fat,err,warn, 1:normal, 2:debug, 3:trace) 505# @param string _log (0|1|2|3) Current set file logging level (0:off, 1:normal, 2:debug, 3:trace) 506# @param integer _file Full path to logfile 507# @return integer 0 508debug() { 509 _lvl="${1}" # Assigned log level: "trace", "debug", "info", "warn" or "err" "fatal" 510 _msg="${2}" # Message (single-line or multiline) 511 _ver="${3}" # (0|1|2|3) Current set verbosity level (0:fat,err,warn, 1:normal, 2:debug, 3:trace) 512 _log="${4}" # (0|1|2|3) Current set file logging level (0:off, 1:normal, 2:debug, 3:trace) 513 _file="${5}" # Full path to logfile 514 515 516 # Separate _lvl which could be in format: 517 # "err|(RUN): " 518 _pre="$( echo "${_lvl}" | awk -F '|' '{print $2}' )" # Get prefix if it exists behind a '|' separator 519 _lvl="$( echo "${_lvl}" | awk -F '|' '{print $1}' )" # Extract _lvl (must be 2nd line, as it overwrites itself) 520 521 522 # Make sure this function is used correctly 523 if [ "${#}" != "5" ]; then 524 _abort_on_internal_error "debug()" "\$#" "${#}" 525 fi 526 if [ "${_lvl}" != "trace" ] && [ "${_lvl}" != "debug" ] && [ "${_lvl}" != "info" ] && [ "${_lvl}" != "ok" ] && [ "${_lvl}" != "err" ] && [ "${_lvl}" != "warn" ] && [ "${_lvl}" != "fatal" ]; then 527 _abort_on_internal_error "debug()" "\$_lvl" "${_lvl}" 528 fi 529 if [ "${_ver}" != "0" ] && [ "${_ver}" != "1" ] && [ "${_ver}" != "2" ] && [ "${_ver}" != "3" ]; then 530 _abort_on_internal_error "debug()" "\$_ver" "${_ver}" 531 fi 532 if [ "${_log}" != "0" ] && [ "${_log}" != "1" ] && [ "${_log}" != "2" ] && [ "${_log}" != "3" ]; then 533 _abort_on_internal_error "debug()" "\$_log" "${_log}" 534 fi 535 536 537 # Prefixes for severity level and date 538 _pre_level="$( _get_severity_level_prefix "${_lvl}" )" # e.g.: "[DEBUG]" or [ERR], etc 539 _pre_color="$( _get_severity_color_prefix "${_lvl}" )" # e.g.: Red color code for error 540 _pre_date="$( date '+%Y-%m-%d %H:%M:%S' )" 541 542 543 # Remove empty lines and lines which only contain spaces from $_msg 544 _msg="$( echo "${_msg}" | sed '/^[[:space:]]*$/d' )" 545 546 547 # 548 # ---------- [OUT] to stdout or stderr ---------- 549 # 550 551 552 # 553 # 1.) [OUT] Always output '[fatal], [error] and [warning] to stderr 554 # 555 if [ "${_lvl}" = "fatal" ] || [ "${_lvl}" = "err" ] || [ "${_lvl}" = "warn" ]; then 556 _coutr "stderr" "${_pre_color}${_pre_level} ${_pre}" "${_msg}" "${CLR_RESET}" 557 fi 558 559 # 560 # 2.) [OUT] Highest verbosity (Trace mode: -vv) 561 # 562 if [ "${_ver}" = "3" ]; then 563 if [ "${_lvl}" = "trace" ] || [ "${_lvl}" = "debug" ] || [ "${_lvl}" = "info" ] || [ "${_lvl}" = "ok" ]; then 564 _coutr "stdout" "${_pre_color}${_pre_level} ${_pre}" "${_msg}" "${CLR_RESET}" 565 fi 566 fi 567 568 # 569 # 3.) [OUT] Debug verbosity (Debug mode: -v) 570 # 571 if [ "${_ver}" = "2" ]; then 572 if [ "${_lvl}" = "debug" ] || [ "${_lvl}" = "info" ] || [ "${_lvl}" = "ok" ]; then 573 _coutr "stdout" "${_pre_color}${_pre_level} ${_pre}" "${_msg}" "${CLR_RESET}" 574 fi 575 fi 576 577 # 578 # 4.) [OUT] Normal verbosity (Normal mode) 579 # 580 if [ "${_ver}" = "1" ]; then 581 if [ "${_lvl}" = "info" ] || [ "${_lvl}" = "ok" ]; then 582 _coutr "stdout" "${_pre_color}${_pre_level} ${_pre}" "${_msg}" "${CLR_RESET}" 583 fi 584 fi 585 586 587 # 588 # ---------- [FILE] to logfile ---------- 589 # 590 591 # 592 # 5.) [FILE] Highest log level (LOG=3) 593 # 594 if [ "${_log}" = "3" ]; then 595 _coutr "${_file}" "${_pre_date} ${_pre_level} ${_pre}" "${_msg}" "" 596 fi 597 598 # 599 # 6.) [FILE] Debug log level (LOG=2) 600 # 601 if [ "${_log}" = "2" ]; then 602 if [ "${_lvl}" = "debug" ] || [ "${_lvl}" = "info" ] || [ "${_lvl}" = "ok" ] || [ "${_lvl}" = "warn" ] || [ "${_lvl}" = "err" ] || [ "${_lvl}" = "fatal" ]; then 603 _coutr "${_file}" "${_pre_date} ${_pre_level} ${_pre}" "${_msg}" "" 604 fi 605 fi 606 607 # 608 # 6.) [FILE] Normal log level (LOG=1) 609 # 610 if [ "${_log}" = "1" ]; then 611 if [ "${_lvl}" = "info" ] || [ "${_lvl}" = "ok" ] || [ "${_lvl}" = "warn" ] || [ "${_lvl}" = "err" ] || [ "${_lvl}" = "fatal" ]; then 612 _coutr "${_file}" "${_pre_date} ${_pre_level} ${_pre}" "${_msg}" "" 613 fi 614 fi 615 616 return 0 617} 618 619# 620# Single-line inline output (without prefix and without newline) to stdout/stderr and/or logfile. 621# 622# @public 623# 624# @param string _lvl Assigned log level: "trace", "debug", "info", "warn" or "err" "fatal" 625# @param string _msg Message (single-line or multiline) 626# @param integer _ver (0|1|2|3) Current set verbosity level (0:fat,err,warn, 1:normal, 2:debug, 3:trace) 627# @param string _log (0|1|2|3) Current set file logging level (0:off, 1:normal, 2:debug, 3:trace) 628# @param integer _file Full path to logfile 629# @return integer 0 630debug_i() { 631 _lvl="${1}" # Assigned log level: "trace", "debug", "info", "warn" or "err" "fatal" 632 _msg="${2}" # Message (single-line or multiline) 633 _ver="${3}" # (0|1|2|3) Current set verbosity level (0:fat,err,warn, 1:normal, 2:debug, 3:trace) 634 _log="${4}" # (0|1|2|3) Current set file logging level (0:off, 1:normal, 2:debug, 3:trace) 635 _file="${5}" # Full path to logfile 636 637 # Make sure this function is used correctly 638 if [ "${#}" != "5" ]; then 639 _abort_on_internal_error "debug_i()" "\$#" "${#}" 640 fi 641 if [ "${_lvl}" != "trace" ] && [ "${_lvl}" != "debug" ] && [ "${_lvl}" != "info" ] && [ "${_lvl}" != "ok" ] && [ "${_lvl}" != "err" ] && [ "${_lvl}" != "warn" ] && [ "${_lvl}" != "fatal" ]; then 642 _abort_on_internal_error "debug_i()" "\$_lvl" "${_lvl}" 643 fi 644 if [ "${_ver}" != "0" ] && [ "${_ver}" != "1" ] && [ "${_ver}" != "2" ] && [ "${_ver}" != "3" ]; then 645 _abort_on_internal_error "debug_i()" "\$_ver" "${_ver}" 646 fi 647 if [ "${_log}" != "0" ] && [ "${_log}" != "1" ] && [ "${_log}" != "2" ] && [ "${_log}" != "3" ]; then 648 _abort_on_internal_error "debug_i()" "\$_log" "${_log}" 649 fi 650 651 652 653 # Prefixes for severity level and date 654 _pre_color="$( _get_severity_color_prefix "${_lvl}" )" # e.g.: Red color code for error 655 656 # Prefix the line? 657 _pre_date="" 658 _pre_level="" 659 660 661 # Remove empty lines and lines which only contain spaces from $_msg 662 #_msg="$( echo "${_msg}" | sed '/^[[:space:]]*$/d' )" 663 664 665 # 666 # ---------- [OUT] to stdout or stderr ---------- 667 # 668 669 670 # 671 # 1.) [OUT] Always output '[fatal], [error] and [warning] to stderr 672 # 673 if [ "${_lvl}" = "fatal" ] || [ "${_lvl}" = "err" ] || [ "${_lvl}" = "warn" ]; then 674 _couti "stderr" "${_pre_color}${_pre_level} " "${_msg}" "${CLR_RESET}" 675 fi 676 677 # 678 # 2.) [OUT] Highest verbosity (Trace mode: -vv) 679 # 680 if [ "${_ver}" = "3" ]; then 681 if [ "${_lvl}" = "trace" ] || [ "${_lvl}" = "debug" ] || [ "${_lvl}" = "info" ] || [ "${_lvl}" = "ok" ]; then 682 _couti "stdout" "${_pre_color}${_pre_level} " "${_msg}" "${CLR_RESET}" 683 fi 684 fi 685 686 # 687 # 3.) [OUT] Debug verbosity (Debug mode: -v) 688 # 689 if [ "${_ver}" = "2" ]; then 690 if [ "${_lvl}" = "debug" ] || [ "${_lvl}" = "info" ] || [ "${_lvl}" = "ok" ]; then 691 _couti "stdout" "${_pre_color}${_pre_level} " "${_msg}" "${CLR_RESET}" 692 fi 693 fi 694 695 # 696 # 4.) [OUT] Normal verbosity (Normal mode) 697 # 698 if [ "${_ver}" = "1" ]; then 699 if [ "${_lvl}" = "info" ] || [ "${_lvl}" = "ok" ]; then 700 _couti "stdout" "${_pre_color}${_pre_level} " "${_msg}" "${CLR_RESET}" 701 fi 702 fi 703 704 705 # 706 # ---------- [FILE] to logfile ---------- 707 # 708 709 # 710 # 5.) [FILE] Highest log level (LOG=3) 711 # 712 if [ "${_log}" = "3" ]; then 713 _couti "${_file}" "${_pre_date} ${_pre_level} " "${_msg}" "" 714 fi 715 716 # 717 # 6.) [FILE] Debug log level (LOG=2) 718 # 719 if [ "${_log}" = "2" ]; then 720 if [ "${_lvl}" = "debug" ] || [ "${_lvl}" = "info" ] || [ "${_lvl}" = "ok" ] || [ "${_lvl}" = "warn" ] || [ "${_lvl}" = "err" ] || [ "${_lvl}" = "fatal" ]; then 721 _couti "${_file}" "${_pre_date} ${_pre_level} " "${_msg}" "" 722 fi 723 fi 724 725 # 726 # 6.) [FILE] Normal log level (LOG=1) 727 # 728 if [ "${_log}" = "1" ]; then 729 if [ "${_lvl}" = "info" ] || [ "${_lvl}" = "ok" ] || [ "${_lvl}" = "warn" ] || [ "${_lvl}" = "err" ] || [ "${_lvl}" = "fatal" ]; then 730 _couti "${_file}" "${_pre_date} ${_pre_level} " "${_msg}" "" 731 fi 732 fi 733 734 return 0 735} 736 737 738# 739# Single-line inline output with prefix (without newline) to stdout/stderr and/or logfile. 740# 741# @public 742# 743# @param string _lvl Assigned log level: "trace", "debug", "info", "warn" or "err" "fatal" 744# @param string _msg Message (single-line or multiline) 745# @param integer _ver (0|1|2|3) Current set verbosity level (0:fat,err,warn, 1:normal, 2:debug, 3:trace) 746# @param string _log (0|1|2|3) Current set file logging level (0:off, 1:normal, 2:debug, 3:trace) 747# @param integer _file Full path to logfile 748# @return integer 0 749debug_pi() { 750 _lvl="${1}" # Assigned log level: "trace", "debug", "info", "warn" or "err" "fatal" 751 _msg="${2}" # Message (single-line or multiline) 752 _ver="${3}" # (0|1|2|3) Current set verbosity level (0:fat,err,warn, 1:normal, 2:debug, 3:trace) 753 _log="${4}" # (0|1|2|3) Current set file logging level (0:off, 1:normal, 2:debug, 3:trace) 754 _file="${5}" # Full path to logfile 755 756 # Make sure this function is used correctly 757 if [ "${#}" != "5" ]; then 758 _abort_on_internal_error "debug_pi()" "\$#" "${#}" 759 fi 760 if [ "${_lvl}" != "trace" ] && [ "${_lvl}" != "debug" ] && [ "${_lvl}" != "info" ] && [ "${_lvl}" != "ok" ] && [ "${_lvl}" != "err" ] && [ "${_lvl}" != "warn" ] && [ "${_lvl}" != "fatal" ]; then 761 _abort_on_internal_error "debug_pi()" "\$_lvl" "${_lvl}" 762 fi 763 if [ "${_ver}" != "0" ] && [ "${_ver}" != "1" ] && [ "${_ver}" != "2" ] && [ "${_ver}" != "3" ]; then 764 _abort_on_internal_error "debug_pi()" "\$_ver" "${_ver}" 765 fi 766 if [ "${_log}" != "0" ] && [ "${_log}" != "1" ] && [ "${_log}" != "2" ] && [ "${_log}" != "3" ]; then 767 _abort_on_internal_error "debug_pi()" "\$_log" "${_log}" 768 fi 769 770 771 # Prefixes for severity level and date 772 _pre_color="$( _get_severity_color_prefix "${_lvl}" )" # e.g.: Red color code for error 773 774 _pre_date="$( date '+%Y-%m-%d %H:%M:%S' )" 775 _pre_level="$( _get_severity_level_prefix "${_lvl}" )" # e.g.: "[DEBUG]" or [ERR], etc 776 777 778 # Remove empty lines and lines which only contain spaces from $_msg 779 #_msg="$( echo "${_msg}" | sed '/^[[:space:]]*$/d' )" 780 781 782 # 783 # ---------- [OUT] to stdout or stderr ---------- 784 # 785 786 787 # 788 # 1.) [OUT] Always output '[fatal], [error] and [warning] to stderr 789 # 790 if [ "${_lvl}" = "fatal" ] || [ "${_lvl}" = "err" ] || [ "${_lvl}" = "warn" ]; then 791 _couti "stderr" "${_pre_color}${_pre_level} " "${_msg}" "${CLR_RESET}" 792 fi 793 794 # 795 # 2.) [OUT] Highest verbosity (Trace mode: -vv) 796 # 797 if [ "${_ver}" = "3" ]; then 798 if [ "${_lvl}" = "trace" ] || [ "${_lvl}" = "debug" ] || [ "${_lvl}" = "info" ] || [ "${_lvl}" = "ok" ]; then 799 _couti "stdout" "${_pre_color}${_pre_level} " "${_msg}" "${CLR_RESET}" 800 fi 801 fi 802 803 # 804 # 3.) [OUT] Debug verbosity (Debug mode: -v) 805 # 806 if [ "${_ver}" = "2" ]; then 807 if [ "${_lvl}" = "debug" ] || [ "${_lvl}" = "info" ] || [ "${_lvl}" = "ok" ]; then 808 _couti "stdout" "${_pre_color}${_pre_level} " "${_msg}" "${CLR_RESET}" 809 fi 810 fi 811 812 # 813 # 4.) [OUT] Normal verbosity (Normal mode) 814 # 815 if [ "${_ver}" = "1" ]; then 816 if [ "${_lvl}" = "info" ] || [ "${_lvl}" = "ok" ]; then 817 _couti "stdout" "${_pre_color}${_pre_level} " "${_msg}" "${CLR_RESET}" 818 fi 819 fi 820 821 822 # 823 # ---------- [FILE] to logfile ---------- 824 # 825 826 # 827 # 5.) [FILE] Highest log level (LOG=3) 828 # 829 if [ "${_log}" = "3" ]; then 830 _couti "${_file}" "${_pre_date} ${_pre_level} " "${_msg}" "" 831 fi 832 833 # 834 # 6.) [FILE] Debug log level (LOG=2) 835 # 836 if [ "${_log}" = "2" ]; then 837 if [ "${_lvl}" = "debug" ] || [ "${_lvl}" = "info" ] || [ "${_lvl}" = "ok" ] || [ "${_lvl}" = "warn" ] || [ "${_lvl}" = "err" ] || [ "${_lvl}" = "fatal" ]; then 838 _couti "${_file}" "${_pre_date} ${_pre_level} " "${_msg}" "" 839 fi 840 fi 841 842 # 843 # 6.) [FILE] Normal log level (LOG=1) 844 # 845 if [ "${_log}" = "1" ]; then 846 if [ "${_lvl}" = "info" ] || [ "${_lvl}" = "ok" ] || [ "${_lvl}" = "warn" ] || [ "${_lvl}" = "err" ] || [ "${_lvl}" = "fatal" ]; then 847 _couti "${_file}" "${_pre_date} ${_pre_level} " "${_msg}" "" 848 fi 849 fi 850 851 return 0 852} 853 854 855 856 857################################################################################ 858# 859# M A T H F U N C T I O N S 860# 861################################################################################ 862 863 864# Test if argument is an integer. 865# 866# @param mixed 867# @return integer 0: is number | 1: not a number 868isint(){ 869 printf "%d" "${1}" >/dev/null 2>&1 && return 0 || return 1; 870} 871 872 873# Sum up two numbers. 874# 875# @param float/integer 876# @param float/integer 877# @output float/integer 878sum() { 879 echo | awk -v "a=${1}" -v "b=${2}" '{print a + b}' 880} 881 882# Subtract two numbers. 883# 884# @param float/integer 885# @param float/integer 886# @output float/integer 887sub() { 888 echo | awk -v "a=${1}" -v "b=${2}" '{print a - b}' 889} 890 891# Divide two numbers. 892# 893# @param float/integer 894# @param float/integer 895# @output float/integer 896div() { 897 echo | awk -v "a=${1}" -v "b=${2}" '{print a / b}' 898} 899 900 901 902# Round a number 903# 904# @param float Number to round 905# @param integer Decimal places 906# @output float Result 907round() { 908 _number="${1}" 909 _precision="${2}" 910 911 # Note this is a locale dependent usage of printf 912 # Separators are assumed '.' and not ',' 913 # This is fixed via setting LC_ALL=C and LANG=C 914 # at the very top of this script. 915 printf '%.*f\n' "${_precision}" "${_number}" 916} 917 918 919################################################################################ 920# 921# S T R I N G F U N C T I O N S 922# 923################################################################################ 924 925 926# 927# Get the length of a string. 928# 929# @param string 930# @output integer Length 931str_len() { 932 echo "${1}" | awk '{print length()}' 933} 934 935 936# Concatenate two strings with a glue (separator). 937# Do not add separator if first string is empty. 938# 939# @param string First string 940# @param string Glue 941# @param string Second string 942# @output string Final string 943str_join() { 944 _first="${1}" 945 _glue="${2}" 946 _last="${3}" 947 948 if [ "${_first}" = "" ]; then 949 echo "${_last}"; 950 return 0 951 elif [ "${_last}" = "" ]; then 952 echo "${_first}"; 953 return 0 954 fi 955 956 # Make sure $_glue is within the placeholder part of printf 957 # this way it can also use '\n' and make a real newline 958 printf "%s${_glue}%s\n" "${_first}" "${_last}" 959 return 960} 961 962# Renove a word from a space separated string. 963# 964# @param string Space separated string of words 965# @param string Word to remove 966# @output string Final string 967str_remove_word() { 968 _string="${1}" 969 _word="${2}" 970 971 # Loop over each space separated word line by line 972 for _each in ${_string}; do 973 # Desired word found? 974 # Remove from variable 975 if [ "${_word}" = "${_each}" ]; then 976 _string="$( echo "${_string}" | sed "s/${_word}//" )" 977 fi 978 done 979 980 echo "${_string}" 981} 982 983 984# Get number of lines in a string 985# 986# @param string String 987# @output integer Number of lines 988str_count_lines() { 989 _string="${1}" 990 echo "${_string}" | grep -c '' 991} 992 993 994 995 996################################################################################ 997# 998# D A T E F U N C T I O N S 999# 1000################################################################################ 1001 1002 1003# Timestamp to formated date. 1004# 1005# @param integer Timestamp 1006# @param string Format (e.g.: '%Y-%m-%d %H:%M:%S %Z [%z') 1007# @output string Formated date 1008# @return integer 0:success, 1:fail 1009formatted_timestamp() { 1010 _timestamp="${1}" 1011 _format="${2}" 1012 1013 # BSD / OSX date function 1014 if date -r 1457171267 >/dev/null 2>&1; then 1015 date -r "${_timestamp}" +"${_format}" 1016 return 0 1017 # Linux date 1018 elif date -d @1457171267 >/dev/null 2>&1; then 1019 date -d @"${_timestamp}" +"${_format}" 1020 return 0 1021 fi 1022 echo "${_timestamp}" 1023 1024 return 1 1025} 1026 1027 1028# Get time in sec since unix epoch 1029# 1030# @output integer Time in Seconds 1031# 1032get_time() { 1033 date +%s 1034} 1035 1036# Calculate duration in seconds 1037# 1038# @param integer Unix epoch start time (in seconds) 1039# @output integer Duration in seconds 1040get_duration() { 1041 _start_time="${1}" 1042 _end_time="$(get_time)" 1043 1044 _duration="$((_end_time - _start_time))" 1045 echo "${_duration}" 1046} 1047 1048 1049################################################################################ 1050# 1051# F I L E F U N C T I O N S 1052# 1053################################################################################ 1054 1055 1056 1057# Get the file mtime 1058# When file is modified 1059# 1060# @param string path to file/folder 1061# @output integer File mtime (timestamp) 1062# @return integer Return code 1063get_file_mtime() { 1064 _file="${1}" 1065 _mtime="0" 1066 _exit=0 1067 1068 # Linux version 1069 if ! _mtime="$(stat -c %Y "${_file}" 2>/dev/null)"; then 1070 # OSX/BSD version 1071 if ! _mtime="$(stat -f %m "${_file}" 2>/dev/null)"; then 1072 # Try date 1073 if ! _mtime="$(date -r "${_file}" +%s 2>/dev/null)"; then 1074 _mtime="0" 1075 _exit=1 1076 fi 1077 fi 1078 fi 1079 1080 echo "${_mtime}" 1081 return ${_exit} 1082} 1083 1084 1085# Get the file ctime 1086# When file is modified or when inode changes (chown/chmod) 1087# 1088# @param string path to file/folder 1089# @output integer File mtime (timestamp) 1090# @return integer Return code 1091get_file_ctime() { 1092 _file="${1}" 1093 _ctime="0" 1094 _exit=0 1095 1096 # Linux version 1097 if ! _ctime="$(stat -c %Z "${_file}" 2>/dev/null)"; then 1098 # OSX/BSD version 1099 if ! _ctime="$(stat -f %c "${_file}" 2>/dev/null)"; then 1100 _ctime="0" 1101 _exit=1 1102 fi 1103 fi 1104 1105 echo "${_ctime}" 1106 return ${_exit} 1107} 1108 1109 1110 1111# Get file size in bytes of file or directory. 1112# 1113# @param string path to file/folder 1114# @param char Unit: 'b': Bytes, 'k': KB, 'm': MB, 'g': GB (defaults to 'b') 1115# @output integer File size in bytes 1116# @return integer Return code 1117get_file_size() { 1118 _file="${1}" 1119 _unit="${2}" 1120 _size="0" 1121 _exit=1 1122 1123 _size="$($(which ls) -l "${_file}" 2>/dev/null)" 1124 _exit=$? 1125 _size="$(echo "${_size}" | awk '{print $5}')" 1126 1127 if [ "${_unit}" = "k" ]; then 1128 _size="$( div "${_size}" "1024" )" 1129 _size="$( round "${_size}" "2" )" 1130 elif [ "${_unit}" = "m" ]; then 1131 _size="$( div "${_size}" "1048576" )" 1132 _size="$( round "${_size}" "2" )" 1133 elif [ "${_unit}" = "g" ]; then 1134 _size="$( div "${_size}" "1073741824" )" 1135 _size="$( round "${_size}" "2" )" 1136 fi 1137 1138 echo "${_size}" 1139 return ${_exit} 1140} 1141 1142 1143# Get md5/sha256 hash of file or directory. 1144# 1145# @param string path to file/folder 1146# @param string algo: 'md5' or 'sha256' (defaults to md5) 1147# @output string Hash 1148# @return integer Return code 1149get_file_hash() { 1150 _file="${1}" 1151 _algo="${2}" 1152 _hash="unknown" 1153 _exit=1 1154 1155 if [ "${_algo}" = "sha256" ]; then 1156 if command -v shasum > /dev/null 2>&1 ; then 1157 _hash="$($(which shasum) -a 256 "${_file}" 2>/dev/null)" 1158 _exit=$? 1159 _hash="$(echo "${_hash}" | awk '{print $1}')" 1160 elif command -v sha256sum > /dev/null 2>&1 ; then 1161 _hash="$($(which sha256sum) "${_file}" 2>/dev/null)" 1162 _exit=$? 1163 _hash="$(echo "${_hash}" | awk '{print $1}')" 1164 fi 1165 else 1166 if command -v md5 > /dev/null 2>&1 ; then 1167 _hash="$($(which md5) "${_file}" 2>/dev/null)" 1168 _exit=$? 1169 _hash="$(echo "${_hash}" | awk -F '=' '{print $2}' | awk '{print $1}')" 1170 elif command -v md5sum > /dev/null 2>&1 ; then 1171 _hash="$($(which md5sum) "${_file}" 2>/dev/null)" 1172 _exit=$? 1173 _hash="$(echo "${_hash}" | awk '{print $1}')" 1174 fi 1175 fi 1176 1177 echo "${_hash}" 1178 return ${_exit} 1179} 1180 1181 1182# Get Operating system independent numerical 4-digit chmod value. 1183# 1184# @param string path to file/folder 1185# @output string numerical chmod (4-digit format) 1186# @return integer Return code 1187get_file_chmod() { 1188 _file="${1}" 1189 _perm="000" 1190 _exit=1 1191 1192 # e.g. 640 1193 if [ "$(uname)" = "Linux" ]; then 1194 # If no special permissions are set (no sticky bit...), linux will 1195 # only output the 3 digit number 1196 _perm="$(stat --format '%a' "${_file}" 2>/dev/null)" 1197 _exit=$? 1198 else # Darwin or FreeBSD, OpenBSD, NetBSD 1199 _perm="$(stat -f "%Mp%Lp" "${_file}" 2>/dev/null)" 1200 _exit=$? 1201 fi 1202 1203 # For special cases check the length and add a leading 0 1204 _len="$(echo "${_perm}" | awk '{ print length() }')" 1205 if [ "${_len}" = "3" ]; then 1206 _perm="0${_perm}" 1207 fi 1208 1209 echo "${_perm}" 1210 return ${_exit} 1211} 1212 1213 1214# Get Operating system independent owner of file 1215# 1216# @param string path to file/folder 1217# @output string Owner 1218# @return integer Return code 1219get_file_owner() { 1220 _file="${1}" 1221 _owner="unknown" 1222 _exit=0 1223 1224 # Linux version 1225 if ! _owner="$(stat -c %U "${_file}" 2>/dev/null)"; then 1226 # OSX/BSD version 1227 if ! _owner="$(stat -f %Su "${_file}" 2>/dev/null)"; then 1228 _owner="unknown" 1229 _exit=1 1230 fi 1231 fi 1232 1233 echo "${_owner}" 1234 return ${_exit} 1235} 1236 1237# Get Operating system independent group of file 1238# 1239# @param string path to file/folder 1240# @output string Owner 1241# @return integer Return code 1242get_file_group() { 1243 _file="${1}" 1244 _group="unknown" 1245 _exit=0 1246 1247 # Linux version 1248 if ! _group="$(stat -c %G "${_file}" 2>/dev/null)"; then 1249 # OSX/BSD version 1250 if ! _group="$(stat -f %Sg "${_file}" 2>/dev/null)"; then 1251 _group="unknown" 1252 _exit=1 1253 fi 1254 fi 1255 1256 echo "${_group}" 1257 return ${_exit} 1258} 1259 1260 1261# Get the real path of a file/folder if it is a symlink 1262# 1263# @param string path (file, folder or symlink) 1264# @output string New path 1265# @return integer Success 1266get_file_realpath() { 1267 _file="${1}" 1268 _exit=1 1269 1270 _path="$(realpath "${_file}" 2>/dev/null)" 1271 _exit=$? 1272 1273 # If path not found, return the original specified path 1274 if [ "${_exit}" != "0" ]; then 1275 _path="${_file}" 1276 fi 1277 1278 echo "${_path}" 1279 return "${_exit}" 1280} 1281 1282# Create a temporary directory using mktemp 1283# 1284# @param string Path where the file should be created 1285# @param string Chmod of file 1286# @output string Full path of the created temp file 1287# @return integer Success 1288create_tmp_dir() { 1289 _path="${1}" 1290 _chmod="${2}" 1291 1292 umask "$(chmod_2_umask "${_chmod}")"; 1293 if ! _dir="$( $(which mktemp) -d "${_path}" 2>/dev/null )"; then 1294 return $? 1295 else 1296 echo "${_dir}" 1297 fi 1298 1299 return 0 1300} 1301 1302 1303# Create a temporary file using mktemp 1304# 1305# @param string Path where the file should be created 1306# @param string Chmod of file 1307# @output string Full path of the created temp file 1308# @return integer Success 1309create_tmp_file() { 1310 _path="${1}" 1311 _chmod="${2}" 1312 1313 umask "$(chmod_2_umask "${_chmod}")"; 1314 if ! _file="$( $(which mktemp) "${_path}" 2>/dev/null )"; then 1315 return $? 1316 else 1317 echo "${_file}" 1318 fi 1319 1320 return 0 1321} 1322 1323 1324 1325################################################################################ 1326# 1327# C H M O D F U N C T I O N S 1328# 1329################################################################################ 1330 1331 1332# Validate chmod value. 1333# 1334# @param string numerical chmod 1335# @return boolean 0: valid, 1: invalid 1336valid_chmod() { 1337 _chmod="${1}" 1338 _len="$(echo "${_chmod}" | awk '{ print length() }')" 1339 1340 1341 if [ "${_len}" = "3" ]; then 1342 1343 r="$(echo "${_chmod}" | awk '{print substr($0,1,1)}')" 1344 w="$(echo "${_chmod}" | awk '{print substr($0,2,1)}')" 1345 x="$(echo "${_chmod}" | awk '{print substr($0,3,1)}')" 1346 1347 1348 # Check if it is an integer 1349 if ! isint "${r}" > /dev/null 2>&1 ; then 1350 return 1 1351 elif ! isint "${w}" > /dev/null 2>&1 ; then 1352 return 1 1353 elif ! isint "${x}" > /dev/null 2>&1 ; then 1354 return 1 1355 fi 1356 1357 # Error out 1358 if [ "$r" -lt 0 ] || [ "$r" -gt 7 ]; then 1359 return 1 1360 fi 1361 if [ "$w" -lt 0 ] || [ "$w" -gt 7 ]; then 1362 return 1 1363 fi 1364 if [ "$x" -lt 0 ] || [ "$x" -gt 7 ]; then 1365 return 1 1366 fi 1367 # All good 1368 return 0 1369 1370 elif [ "${_len}" = "4" ]; then 1371 1372 s="$(echo "${_chmod}" | awk '{print substr($0,1,1)}')" 1373 r="$(echo "${_chmod}" | awk '{print substr($0,2,1)}')" 1374 w="$(echo "${_chmod}" | awk '{print substr($0,3,1)}')" 1375 x="$(echo "${_chmod}" | awk '{print substr($0,4,1)}')" 1376 1377 # Check if it is an integer 1378 if ! isint "${s}" > /dev/null 2>&1 ; then 1379 return 1 1380 elif ! isint "${r}" > /dev/null 2>&1 ; then 1381 return 1 1382 elif ! isint "${w}" > /dev/null 2>&1 ; then 1383 return 1 1384 elif ! isint "${x}" > /dev/null 2>&1 ; then 1385 return 1 1386 fi 1387 1388 # Error out 1389 if [ "$s" -lt 0 ] || [ "$s" -gt 7 ]; then 1390 return 1 1391 fi 1392 if [ "$r" -lt 0 ] || [ "$r" -gt 7 ]; then 1393 return 1 1394 fi 1395 if [ "$w" -lt 0 ] || [ "$w" -gt 7 ]; then 1396 return 1 1397 fi 1398 if [ "$x" -lt 0 ] || [ "$x" -gt 7 ]; then 1399 return 1 1400 fi 1401 # All good 1402 return 0 1403 1404 else 1405 # Nope! 1406 return 1 1407 fi 1408} 1409 1410 1411# Compare two chmod values. 1412# 1413# @param string numerical chmod (3 or 4 digits) 1414# @param string numerical chmod (3 or 4 digits) 1415# @return boolean 0: equals, 1: unequal 1416compare_chmod() { 1417 _chmod1="${1}" 1418 _chmod2="${2}" 1419 1420 _len1="$(echo "${_chmod1}" | awk '{ print length() }')" 1421 _len2="$(echo "${_chmod2}" | awk '{ print length() }')" 1422 1423 if [ "${_len1}" = "${_len2}" ]; then 1424 if [ "${_chmod1}" = "${_chmod2}" ]; then 1425 return 0 1426 else 1427 return 1 1428 fi 1429 elif [ "${_len1}" = "3" ] && [ "${_len2}" = "4" ]; then 1430 if [ "0${_chmod1}" = "${_chmod2}" ]; then 1431 return 0 1432 else 1433 return 1 1434 fi 1435 elif [ "${_len1}" = "4" ] && [ "${_len2}" = "3" ]; then 1436 if [ "${_chmod1}" = "0${_chmod2}" ]; then 1437 return 0 1438 else 1439 return 1 1440 fi 1441 else 1442 return 1 1443 fi 1444} 1445 1446 1447# Convert 3-digit or 4-digit chmod to 3-digit umask 1448# 1449# @param string numerical chmod (3 or 4 digit) 1450# @output string 3-digit umask 1451# @return integer 0 1452chmod_2_umask() { 1453 _chmod="${1}" 1454 _len="$(echo "${_chmod}" | awk '{print length()}')" 1455 1456 if [ "${_len}" = "3" ]; then 1457 r=$(echo "${_chmod}" | awk '{print substr($0,1,1)}') 1458 w=$(echo "${_chmod}" | awk '{print substr($0,2,1)}') 1459 x=$(echo "${_chmod}" | awk '{print substr($0,3,1)}') 1460 elif [ "${_len}" = "4" ]; then 1461 r=$(echo "${_chmod}" | awk '{print substr($0,2,1)}') 1462 w=$(echo "${_chmod}" | awk '{print substr($0,3,1)}') 1463 x=$(echo "${_chmod}" | awk '{print substr($0,4,1)}') 1464 fi 1465 1466 ur="$(sub "7" "${r}")" 1467 uw="$(sub "7" "${w}")" 1468 ux="$(sub "7" "${x}")" 1469 1470 echo "${ur}${uw}${ux}" 1471} 1472 1473 1474 1475 1476################################################################################ 1477# 1478# T M P W A T C H F U N C T I O N S 1479# 1480################################################################################ 1481 1482 1483############################################################ 1484# tmpwatch/tmpreaper checker/helper 1485############################################################ 1486 1487# Check for correct tmpwatch/tmpreaper value 1488# 1489# @param string tmpwatch/tmpreaper deletion value (1, 1m, 1h, 1d) 1490# @return integer 0: success, 1: failure 1491valid_tmpwatch() { 1492 _val="${1}" 1493 1494 # No unit (auto-defaults to hours) 1495 if echo "${_val}" | grep -Eq '^[0-9]+$'; then 1496 if [ "${_val}" -gt 0 ]; then 1497 return 0 1498 fi 1499 # 'm' for minutes 1500 elif echo "${_val}" | grep -Eq '^[0-9]+m$'; then 1501 _num="$(echo "${_val}" | sed 's/m//g')" 1502 if [ "${_num}" -gt 0 ]; then 1503 return 0 1504 fi 1505 # 'h' for hours 1506 elif echo "${_val}" | grep -Eq '^[0-9]+h$'; then 1507 _num="$(echo "${_val}" | sed 's/h//g')" 1508 if [ "${_num}" -gt 0 ]; then 1509 return 0 1510 fi 1511 # 'd' for days 1512 elif echo "${_val}" | grep -Eq '^[0-9]+d$'; then 1513 _num="$(echo "${_val}" | sed 's/d//g')" 1514 if [ "${_num}" -gt 0 ]; then 1515 return 0 1516 fi 1517 fi 1518 1519 # Fuck off 1520 return 1 1521} 1522 1523# Get numerical value for tmpwatch/tmpreaper deletions 1524# 1525# @param string tmpwatch/tmpreaper deletion value (1, 1m, 1h, 1d) 1526# @output integer Value 1527# @return integer Success 1528get_tmpwatch_value() { 1529 _val="${1}" 1530 1531 # No unit (auto-defaults to hours) 1532 if echo "${_val}" | grep -Eq '^[0-9]+$'; then 1533 echo "${_val}" 1534 return 0 1535 # 'm' for minutes 1536 elif echo "${_val}" | grep -Eq '^[0-9]+m$'; then 1537 echo "${_val}" | sed 's/m//g' 1538 return 0 1539 # 'h' for hours 1540 elif echo "${_val}" | grep -Eq '^[0-9]+h$'; then 1541 echo "${_val}" | sed 's/h//g' 1542 return 0 1543 # 'd' for days 1544 elif echo "${_val}" | grep -Eq '^[0-9]+d$'; then 1545 echo "${_val}" | sed 's/d//g' 1546 return 0 1547 else 1548 echo "Internal Error: [get_tmpwatch_value] Invalid value for \$_val: '${_val}'" 1549 echo "Please report this at github." 1550 exit 1 1551 fi 1552} 1553 1554# Get human readable unit for tmpwatch/tmpreaper deletions (plural or singular) 1555# 1556# @param string tmpwatch/tmpreaper deletion value (1, 1m, 1h, 1d) 1557# @return string Human readable unit 1558get_tmpwatch_unit_name() { 1559 _val="${1}" 1560 1561 # No unit (auto-defaults to hours) 1562 if echo "${_val}" | grep -Eq '^[0-9]+$'; then 1563 if [ "${_val}" -gt 1 ]; then 1564 echo "hours" 1565 else 1566 echo "hour" 1567 fi 1568 # 'm' for minutes 1569 elif echo "${_val}" | grep -Eq '^[0-9]+m$'; then 1570 _num="$(echo "${_val}" | sed 's/m//g')" 1571 if [ "${_num}" -gt 1 ]; then 1572 echo "minutes" 1573 else 1574 echo "minute" 1575 fi 1576 # 'h' for hours 1577 elif echo "${_val}" | grep -Eq '^[0-9]+h$'; then 1578 _num="$(echo "${_val}" | sed 's/h//g')" 1579 if [ "${_num}" -gt 1 ]; then 1580 echo "hours" 1581 else 1582 echo "hour" 1583 fi 1584 # 'd' for days 1585 elif echo "${_val}" | grep -Eq '^[0-9]+d$'; then 1586 _num="$(echo "${_val}" | sed 's/d//g')" 1587 if [ "${_num}" -gt 1 ]; then 1588 echo "days" 1589 else 1590 echo "day" 1591 fi 1592 else 1593 echo "Internal Error: [get_tmpwatch_unit_name] Invalid value for \$_val: '${_val}'" 1594 echo "Please report this at github." 1595 exit 1 1596 fi 1597} 1598 1599 1600 1601################################################################################ 1602# 1603# N A G I O S F U N C T I O N S 1604# 1605################################################################################ 1606 1607 1608# Aggregate nagios exit code. 1609# 1610# OK < Warning < Error < Unknown 1611# @param integer The current exit code. 1612# @param integer The new exit code 1613# @output integer The combined exit code 1614# @return integer The combined exit code 1615merge_exit_codes() { 1616 _curr_exit="${1}" 1617 _next_exit="${2}" 1618 1619 # OK 1620 if [ "${_curr_exit}" = "0" ]; then 1621 _curr_exit="${_next_exit}" 1622 # Warning 1623 elif [ "${_curr_exit}" = "1" ]; then 1624 if [ "${_next_exit}" = "0" ]; then 1625 _curr_exit="1" 1626 elif [ "${_next_exit}" = "1" ]; then 1627 _curr_exit="1" 1628 elif [ "${_next_exit}" = "2" ]; then 1629 _curr_exit="2" 1630 elif [ "${_next_exit}" = "3" ]; then # UNKNOWN -> WARNING 1631 _curr_exit="1" 1632 fi 1633 # Error 1634 elif [ "${_curr_exit}" = "2" ]; then 1635 _curr_exit="2" 1636 # Unknown 1637 elif [ "${_curr_exit}" = "3" ]; then 1638 if [ "${_next_exit}" = "0" ]; then 1639 _curr_exit="3" 1640 elif [ "${_next_exit}" = "1" ]; then 1641 _curr_exit="1" 1642 elif [ "${_next_exit}" = "2" ]; then 1643 _curr_exit="2" 1644 elif [ "${_next_exit}" = "3" ]; then # UNKNOWN -> WARNING 1645 _curr_exit="3" 1646 fi 1647 fi 1648 echo "${_curr_exit}" 1649 return ${_curr_exit} 1650} 1651 1652 1653 1654 1655 1656################################################################################ 1657# 1658# M Y S Q L F U N C T I O N S 1659# 1660################################################################################ 1661 1662 1663############################################################ 1664# MySQL Connection Helper 1665############################################################ 1666 1667 1668# Test if connection to the server is successful. 1669# 1670# @param string Credentials file (mysqldump-secure.cnf). 1671# @param string SSL connection options. 1672# @output string Error message 1673# @return integer Success (0: OK | 1: Error) 1674mysql_test_connection() { 1675 _cnf_file="${1}" 1676 _ssl_opts="${2}" 1677 _error="" 1678 _errno=0 1679 1680 # Redirect stderr into stdout and both into variable 1681 _error="$( $(which mysql) --defaults-file="${_cnf_file}" "${_ssl_opts}" -e exit 2>&1 )" 1682 _errno=$? 1683 1684 if [ "${_errno}" != "0" ] || [ "${_error}" != "" ]; then 1685 echo "${_error}" 1686 return 1 1687 else 1688 return 0 1689 fi 1690} 1691 1692 1693############################################################ 1694# MySQL Server Info Helper 1695############################################################ 1696 1697# Get MySQL server status 'status;' 1698# 1699# @param string Credentials file (mysqldump-secure.cnf). 1700# @param string SSL connection options. 1701# @output string MySQL 'status;' 1702# @return integer Success (0: OK | 1: Error) 1703get_mysql_server_status() { 1704 _cnf_file="${1}" 1705 _ssl_opts="${2}" 1706 _exit=1 1707 1708 _query="status;" 1709 _result="$( $(which mysql) --defaults-file="${_cnf_file}" "${_ssl_opts}" --batch -e "${_query}" 2>/dev/null)" 1710 _exit=$? 1711 1712 echo "${_result}" 1713 return ${_exit} 1714} 1715 1716# Get MySQL server hostname 1717# 1718# @param string Credentials file (mysqldump-secure.cnf). 1719# @param string SSL connection options. 1720# @output string Hostname 1721# @return integer Success (0: OK | 1: Error) 1722get_mysql_server_hostname() { 1723 _cnf_file="${1}" 1724 _ssl_opts="${2}" 1725 _exit=1 1726 1727 _query="SHOW GLOBAL VARIABLES LIKE 'HOSTNAME';" 1728 1729 # Redirect stderr into stdout and both into variable 1730 _result="$( $(which mysql) --defaults-file="${_cnf_file}" "${_ssl_opts}" --batch -e "${_query}" 2>/dev/null)" 1731 _exit=$? 1732 1733 _result="$( echo "${_result}" | tail -n1 | sed 's/hostname[[:space:]]*//g' )" 1734 1735 echo "${_result}" 1736 return ${_exit} 1737} 1738 1739# Get MySQL server port 1740# 1741# @param string Credentials file (mysqldump-secure.cnf). 1742# @param string SSL connection options. 1743# @output string Port 1744# @return integer Success (0: OK | 1: Error) 1745get_mysql_server_port() { 1746 _cnf_file="${1}" 1747 _ssl_opts="${2}" 1748 _exit=1 1749 1750 _query="SHOW GLOBAL VARIABLES LIKE 'PORT';" 1751 1752 # Redirect stderr into stdout and both into variable 1753 _result="$( $(which mysql) --defaults-file="${_cnf_file}" "${_ssl_opts}" --batch -e "${_query}" 2>/dev/null)" 1754 _exit=$? 1755 1756 _result="$( echo "${_result}" | tail -n1 | sed 's/port[[:space:]]*//g' )" 1757 1758 echo "${_result}" 1759 return ${_exit} 1760} 1761 1762# Determines wheter the server connected to 1763# is 1764# * a master without replication (single) 1765# * a master with replication (master) 1766# * a slave 1767# * or unknown 1768# 1769# @param string Credentials file (mysqldump-secure.cnf). 1770# @param string SSL connection options. 1771# @output string Type (unknown|master|slave) 1772# @return integer Success (0: OK | 1: Error) 1773get_mysql_server_replication_type() { 1774 _cnf_file="${1}" 1775 _ssl_opts="${2}" 1776 _exit=1 1777 1778 _query="select COUNT(1) SlaveThreads from information_schema.processlist where user = 'system user';" 1779 _result="$( $(which mysql) --defaults-file="${_cnf_file}" "${_ssl_opts}" --batch -e "${_query}" 2>/dev/null)" 1780 _exit=$? 1781 1782 _result="$( echo "${_result}" | tail -n1 )" 1783 1784 if [ "${_exit}" != "0" ]; then 1785 echo "unknown" 1786 return ${_exit} 1787 else 1788 if [ "${_result}" = "0" ]; then 1789 echo "master" 1790 return ${_exit} 1791 elif [ "${_result}" -gt "0" ]; then 1792 echo "slave" 1793 return ${_exit} 1794 else 1795 echo "unknown" 1796 return 1 1797 fi 1798 fi 1799} 1800 1801# Get MySQL Server Version 1802# 1803# @param string MySQL server 'status;' output 1804# @output string Server Version 1805# @return integer 0 1806get_mysql_server_version() { 1807 _mysql_server_status="${1}" 1808 1809 echo "${_mysql_server_status}" | grep -E '^Server version:.*' | sed 's/Server version:[[:space:]]*//g' 1810 return 0 1811} 1812 1813# Get MySQL Server Name (MySQL or MariaDB) 1814# 1815# @param string MySQL server 'status;' output 1816# @output string Server name 1817# @return integer 0 1818get_mysql_server_name() { 1819 _mysql_server_status="${1}" 1820 1821 echo "${_mysql_server_status}" | grep -E '^Server:.*' | sed 's/Server:[[:space:]]*//g' 1822 return 0 1823} 1824 1825 1826############################################################ 1827# MySQL Connection Info Helper 1828############################################################ 1829 1830# Get MySQL connection info (TCP/IP or Socket) 1831# 1832# @param string MySQL server 'status;' output 1833# @output string Connection type (TCP/IP or Socket) 1834# @return integer 0 1835get_mysql_connection_type_info() { 1836 _mysql_server_status="${1}" 1837 1838 echo "${_mysql_server_status}" | grep -E '^Connection:.*' | sed 's/Connection:[[:space:]]*//g' 1839 return 0 1840} 1841 1842# Get MySQL connection info about SSL status 1843# 1844# @param string MySQL server 'status;' output 1845# @output string SSL Connection info 1846# @return integer 0 1847get_mysql_connection_ssl_info() { 1848 _mysql_server_status="${1}" 1849 1850 echo "${_mysql_server_status}" | grep -E '^SSL:.*' | sed 's/SSL:[[:space:]]*//g' 1851 return 0 1852} 1853 1854 1855 1856############################################################ 1857# MySQL Database Helper 1858############################################################ 1859 1860 1861# Get all databas names 1862# 1863# @param string Credentials file (mysqldump-secure.cnf). 1864# @param string SSL connection options. 1865# @output string All databases (including empty ones) 1866# @return integer Success (0: OK | 1: Error) 1867get_mysql_databases() { 1868 _cnf_file="${1}" 1869 _ssl_opts="${2}" 1870 _exit=1 1871 1872 _query="show databases;" 1873 _result="$( $(which mysql) --defaults-file="${_cnf_file}" "${_ssl_opts}" --batch -e "${_query}" 2>/dev/null)" 1874 _exit=$? 1875 1876 # Only gets databases which have content (tables) 1877 #DATABASES="$( ${MYSQL} --defaults-file="${MYSQL_CNF_FILE}" "${MYSQL_SSL_ARGS}" --no-auto-rehash --skip-column-names -e 'SELECT DISTINCT table_schema FROM information_schema.tables;')" 1878 1879 # Remove first column (is sql column name) 1880 _result="$( echo "${_result}" | sed 1d )" 1881 1882 # output all databases on success 1883 if [ "${_exit}" = "0" ]; then 1884 echo "${_result}" 1885 fi 1886 1887 return "${_exit}" 1888} 1889 1890# Get database size in btyes 1891# 1892# @param string Credentials file (mysqldump-secure.cnf). 1893# @param string SSL connection options. 1894# @output integer Database size in bytes 1895# @return integer Success (0: OK | 1: Error) 1896get_mysql_database_size() { 1897 _cnf_file="${1}" 1898 _ssl_opts="${2}" 1899 _database="${3}" 1900 _exit=1 1901 1902 _query="SELECT SUM(DATA_LENGTH + INDEX_LENGTH) AS Size 1903 FROM INFORMATION_SCHEMA.TABLES 1904 WHERE TABLE_SCHEMA = '${_database}';" 1905 1906 1907 _result="$( $(which mysql) --defaults-file="${_cnf_file}" "${_ssl_opts}" --batch -e "${_query}" 2>/dev/null)" 1908 _exit=$? 1909 1910 _result="$( echo "${_result}" | tail -n1 )" 1911 1912 echo "${_result}" 1913 return ${_exit} 1914} 1915 1916# Determines whether database is empty 1917# 1918# @param string Credentials file (mysqldump-secure.cnf). 1919# @param string SSL connection options. 1920# @return integer 0: Empty | 1: Not empty 1921mysql_database_is_empty() { 1922 _cnf_file="${1}" 1923 _ssl_opts="${2}" 1924 _database="${3}" 1925 1926 1927 # If a database does not show up in information_schema.tables, it means it 1928 # has no tables yet and is therefore empty. 1929 # If count == 0, return '0', else '1' 1930 _query="SELECT IF(COUNT(*) = 0, '0', '1') AS empty 1931 FROM INFORMATION_SCHEMA.TABLES 1932 WHERE TABLE_SCHEMA = '${_database}';" 1933 1934 _result="$( $(which mysql) --defaults-file="${_cnf_file}" "${_ssl_opts}" --batch -e "${_query}" 2>/dev/null)" 1935 _result="$( echo "${_result}" | tail -n1 )" 1936 1937 return "${_result}" 1938} 1939 1940############################################################ 1941# Table Helper Helper 1942############################################################ 1943 1944# Count all InnoDB tables 1945# 1946# @param string Credentials file (mysqldump-secure.cnf). 1947# @param string SSL connection options. 1948# @param string Database. 1949count_innodb_tables() { 1950 _cnf_file="${1}" 1951 _ssl_opts="${2}" 1952 _database="${3}" 1953 _exit=1 1954 1955 _query="SELECT COUNT(TABLE_NAME) AS cnt 1956 FROM information_schema.TABLES 1957 WHERE ENGINE = 'InnoDB' 1958 AND TABLE_SCHEMA = '${_database}';" 1959 1960 _result="$( $(which mysql) --defaults-file="${_cnf_file}" "${_ssl_opts}" --batch -e "${_query}" 2>/dev/null)" 1961 _result="$( echo "${_result}" | tail -n1 )" 1962 1963 echo "${_result}" 1964} 1965 1966# Count all InnoDB tables 1967# 1968# @param string Credentials file (mysqldump-secure.cnf). 1969# @param string SSL connection options. 1970# @param string Database. 1971count_non_innodb_tables() { 1972 _cnf_file="${1}" 1973 _ssl_opts="${2}" 1974 _database="${3}" 1975 _exit=1 1976 1977 _query="SELECT COUNT(TABLE_NAME) AS cnt 1978 FROM information_schema.TABLES 1979 WHERE ENGINE <> 'InnoDB' 1980 AND TABLE_SCHEMA = '${_database}';" 1981 1982 _result="$( $(which mysql) --defaults-file="${_cnf_file}" "${_ssl_opts}" --batch -e "${_query}" 2>/dev/null)" 1983 _result="$( echo "${_result}" | tail -n1 )" 1984 1985 echo "${_result}" 1986} 1987 1988# Count all tables 1989# 1990# @param string Credentials file (mysqldump-secure.cnf). 1991# @param string SSL connection options. 1992# @param string Database. 1993count_total_tables() { 1994 _cnf_file="${1}" 1995 _ssl_opts="${2}" 1996 _database="${3}" 1997 _exit=1 1998 1999 _query="SELECT COUNT(TABLE_NAME) AS cnt 2000 FROM information_schema.TABLES 2001 WHERE TABLE_SCHEMA = '${_database}';" 2002 2003 _result="$( $(which mysql) --defaults-file="${_cnf_file}" "${_ssl_opts}" --batch -e "${_query}" 2>/dev/null)" 2004 _result="$( echo "${_result}" | tail -n1 )" 2005 2006 echo "${_result}" 2007} 2008 2009 2010 2011################################################################################ 2012# 2013# D A T A B A S E I G N O R E / R E Q U I R E H E L P E R 2014# 2015################################################################################ 2016 2017# Check if the specified database should be ignored 2018# This can either be by the full name or a wildcard with '*' 2019# 2020# @param string Ignore list 2021# @param string Database name 2022# @output string Ignore pattern 2023# @return integer 0: ignored, 1: not ignored 2024database_is_ignored() { 2025 _ignore_list="${1}" 2026 _database="${2}" 2027 2028 # Default exit with 1, which means 2029 # it was not found. 2030 _exit=1 2031 2032 # The ignore pattern if it was ignored 2033 _pattern="" 2034 2035 # We need to disable "variable globbing" (set -f) here, 2036 # because if there is only a '*' inside '$IGNORE' 2037 # then 2038 # 'for ign_db in ${IGNORE}; do' 2039 # would list all files in the current directory. 2040 set -f 2041 for _ignore_pattern in ${_ignore_list}; do 2042 2043 # Replace '*' with '.*' to create a regex pattern 2044 _regex="$(echo "${_ignore_pattern}" | sed 's/\*/\.\*/')" 2045 2046 # Check if the pattern matches the complete db name 2047 _found="$(echo "${_database}" | grep -oe "${_regex}")" 2048 2049 if [ "${_found}" = "${_database}" ]; then 2050 2051 # Assign new ignore pattern 2052 _pattern="${_ignore_pattern}" 2053 2054 # Return with 0 to indicate it was found 2055 _exit=0 2056 2057 # Stop the loop 2058 break 2059 fi 2060 done 2061 set +f 2062 2063 echo "${_pattern}" 2064 return ${_exit} 2065} 2066 2067# Check if the specified database is required. 2068# 2069# @param string Require list 2070# @param string Database name 2071# @return integer 0: required, 1: not required 2072database_is_required() { 2073 _require_list="${1}" 2074 _database="${2}" 2075 2076 # Now check if the ignored db is actually a required db inside $REQUIRE 2077 for _db_required in ${_require_list}; do 2078 # Required database found? 2079 if [ "${_database}" = "${_db_required}" ]; then 2080 # Returning 0 indicates it is required 2081 return 0 2082 fi 2083 done 2084 2085 # Returning invalid return code indicates it is not required 2086 return 1 2087 2088} 2089 2090 2091################################################################################ 2092# 2093# M I S C F U N C T I O N S 2094# 2095################################################################################ 2096 2097 2098 2099 2100# Determine the file extension 2101# based on encrypted/compressed files 2102# 2103# @param integer _encrypt Encryption enabled? (0: off | 1: on) 2104# @param integer _compress Compression enabled? (0: off | 1: on) 2105# @param string _compress_ext Compression extension (e.g.: gz) 2106# @output string File extension 2107build_file_extension() { 2108 _encrypt="${1}" 2109 _compress="${2}" 2110 _compress_ext="${3}" 2111 2112 # Get file extension 2113 if [ "${_compress}" = "1" ]; then 2114 if [ "${_encrypt}" = "1" ]; then 2115 echo ".sql.${_compress_ext}.enc" 2116 else 2117 echo ".sql.${_compress_ext}" 2118 fi 2119 else 2120 if [ "${_encrypt}" = "1" ]; then 2121 echo ".sql.enc" 2122 else 2123 echo ".sql" 2124 fi 2125 fi 2126} 2127 2128 2129 2130# Validate mysqldump-secure.cnf file 2131# 2132# The only allowed directives are: 2133# [client] 2134# socket = 2135# host = 2136# port = 2137# user = 2138# password = 2139# "[client]" must also be the first non-commented 2140# directive. 2141# 2142# @param string mysqldump-secure.cnf file path 2143# @output string Error message 2144# @return integer 0: valid | 1: invalid 2145validate_cnf_file() { 2146 _file_path="${1}" 2147 2148 # Get contents 2149 cnf="$(cat "${_file_path}")" 2150 2151 # Remove line comments ('#' and ';') 2152 cnf="$(echo "${cnf}" | sed 's/^[[:space:]]*#.*$//g')" 2153 cnf="$(echo "${cnf}" | sed 's/^[[:space:]]*;.*$//g')" 2154 2155 # Remove empty lines 2156 cnf="$(echo "${cnf}" | sed '/^$/d')" 2157 2158 # Remove leading spaces 2159 cnf="$(echo "${cnf}" | sed 's/^[[:space:]]*//g')" 2160 2161 # Remove trailing spaces 2162 cnf="$(echo "${cnf}" | sed 's/[[:space:]]*$//g')" 2163 2164 IFS=' 2165 ' 2166 i=0 2167 set -f 2168 for _line in ${cnf}; do 2169 i=$((i + 1)) 2170 2171 # Everything before the '=' is the actual directive to check against 2172 # E.g: "host = localhost" results in "host" 2173 _directive="$(echo "${_line}" | awk -F '=' '{print $1}' | sed 's/^[[:space:]]*//g' | sed 's/[[:space:]]*$//g')" 2174 2175 # Check for '[client]' in the first non-commented line 2176 if [ "${i}" = "1" ] && [ "${_line}" != "[client]" ]; then 2177 echo "The first non-commented line must contain a \"[client]\" directive" 2178 return 1 2179 fi 2180 2181 # Only allow the following directives 2182 if [ "${_directive}" != "[client]" ] && 2183 [ "${_directive}" != "socket" ] && 2184 [ "${_directive}" != "host" ] && 2185 [ "${_directive}" != "port" ] && 2186 [ "${_directive}" != "user" ] && 2187 [ "${_directive}" != "password" ]; then 2188 echo "Invalid directive found: \"${_directive}\"" 2189 return 1 2190 fi 2191 2192 done 2193 set +f 2194 unset IFS 2195 2196 # All fine, nothing bad found. 2197 return 0 2198} 2199 2200 2201 2202################################################################################ 2203# 2204# M Y S Q L D U M P F U N CT I O N S 2205# 2206################################################################################ 2207 2208# Get mysqldump consistency options based on database and settings. 2209# 2210# @param integer Settings for InnoDB only Database 2211# @param integer Settings for mixed InnoDB and others Database 2212# @param integer Settings for non-InnoDB Database 2213# @param integer How many InnoDB tables 2214# @param integer How many non-InnoDB tables 2215# @output string Mysqldump consistency options 2216# @return integer 0 2217get_consistency_opts() { 2218 _consistent_dump_only_innodb="${1}" 2219 _consistent_dump_mixed_innodb="${2}" 2220 _consistent_dump_no_innodb="${3}" 2221 _tbl_cnt_innodb="${4}" 2222 _tbl_cnt_others="${5}" 2223 2224 2225 # Default is to ignore locks completely 2226 _lock_opts="--skip-lock-tables" 2227 2228 # 2229 # Case 1: Only InnoDB Tables 2230 # 2231 if [ "${_tbl_cnt_others}" = "0" ]; then 2232 # Apply consistency to InnoDB 2233 if [ "${_consistent_dump_only_innodb}" = "1" ]; then 2234 _lock_opts="--single-transaction" 2235 else 2236 _lock_opts="--skip-lock-tables" 2237 fi 2238 # 2239 # Case 2: InnoDB + Other Tables 2240 # 2241 elif [ "${_tbl_cnt_innodb}" != "0" ] && [ "${_tbl_cnt_others}" != "0" ]; then 2242 # Apply consistency to InnoDB 2243 if [ "${_consistent_dump_mixed_innodb}" = "1" ]; then 2244 _lock_opts="--lock-tables" 2245 elif [ "${_consistent_dump_mixed_innodb}" = "2" ]; then 2246 _lock_opts="--single-transaction" 2247 else 2248 _lock_opts="--skip-lock-tables" 2249 fi 2250 # 2251 # Case 3: No InnoDB Tables 2252 # 2253 elif [ "${_tbl_cnt_innodb}" = "0" ]; then 2254 # Apply consistency to InnoDB 2255 if [ "${_consistent_dump_no_innodb}" = "1" ]; then 2256 _lock_opts="--lock-tables" 2257 else 2258 _lock_opts="--skip-lock-tables" 2259 fi 2260 # 2261 # Case 4: FALLBACK 2262 # 2263 else 2264 _lock_opts="--skip-lock-tables" 2265 fi 2266 2267 echo "${_lock_opts}" 2268 return 0 2269} 2270 2271# Run the actualy mysqldump here 2272# 2273# @param integer Dump mode (0: plain, 1: compressed, 2: encrypted, 3: compressed & encrypted) 2274# @param string MySQL connection args (cnf file and SSL arguments) 2275# @param string Database name 2276# @param string Destination file full path 2277# @param integer Destination file chmod 2278# @param string Name of compression binary (e.g.: gzip) 2279# @param string Compression arguments (e.g.: -9) 2280# @param string OpenSSL asymmetric encryption algorithm (e.g.: -aes256) 2281# @param string OpenSSL full path to public key file 2282# @param string Full path to temporary directory 2283# @output string Multiline string of pipefail errors/warnings/success 2284# @return integer 0 2285run_mysqldump() { 2286 _dump_mode="${1}" # 0: plain, 1: compressed, 2: encrypted, 3: compressed & encrypted 2287 _mysql_arg="${2}" # mysql connection args, ssl and mysqldump arguments 2288 _database="${3}" # which database to dump 2289 _file_name="${4}" 2290 _file_chmod="${5}" 2291 _compress_bin="${6}" 2292 _compress_arg="${7}" 2293 _openssl_algo="${8}" 2294 _openssl_cert="${9}" 2295 _tmp_dir="${10}" 2296 2297 2298 _error_statuses="" 2299 2300 # 2301 # 0: Plain 2302 # 2303 if [ "${_dump_mode}" = "0" ]; then 2304 2305 # Temp file 'mysqldump' 2306 _err_tmp_file_dump="" 2307 _ern_tmp_file_dump="0" 2308 if ! _tmp_file_dump="$( create_tmp_file "${_tmp_dir}/.dump_XXXXXXXXXXXXXXX" "0600" 2>/dev/null)"; then 2309 _err_tmp_file_dump="Could not create tmp file in ${_tmp_dir}" 2310 _ern_tmp_file_dump="1" 2311 fi 2312 2313 # Set umask prior writing, so we get the correct chmod just at the time of writing to disk 2314 umask "$(chmod_2_umask "${_file_chmod}")"; 2315 2316 # POSIX pipefail emulation 2317 exec 4>&1 2318 # Ignore ${_mysql_arg} to be quoted 2319 # shellcheck disable=SC2086 2320 _error_statuses="$( ( 2321 ( 2322 $(which mysqldump) ${_mysql_arg} "${_database}" 2> "${_tmp_file_dump}" > "${_file_name}"; 2323 printf "%s\n%s\n" \ 2324 "0:$?:$(head -n1 "${_tmp_file_dump}")" \ 2325 "3:${_ern_tmp_file_dump}:${_err_tmp_file_dump}" >&3; 2326 ) 2327 ) 3>&1 >&4)" 2328 exec 4>&- 2329 2330 # Delete tmp file 2331 if [ "${_ern_tmp_file_dump}" = "0" ]; then 2332 if [ ! -f "${_tmp_file_dump}" ]; then 2333 _error_statuses="$( printf "${_error_statuses}\n%s\n" "6:1:tmp file does not exist ${_tmp_file_dump}" )" 2334 elif ! rm "${_tmp_file_dump}" 2>/dev/null; then 2335 _error_statuses="$( printf "${_error_statuses}\n%s\n" "6:1:Could not delete tmp file ${_tmp_file_dump}" )" 2336 fi 2337 fi 2338 2339 2340 # 2341 # 1: Compressed 2342 # 2343 elif [ "${_dump_mode}" = "1" ]; then 2344 2345 # Temp file 'mysqldump' 2346 _err_tmp_file_dump="" 2347 _ern_tmp_file_dump="0" 2348 if ! _tmp_file_dump="$( create_tmp_file "${_tmp_dir}/.dump_XXXXXXXXXXXXXXX" "0600" 2>/dev/null)"; then 2349 _err_tmp_file_dump="Could not create tmp file ${_tmp_dir}" 2350 _ern_tmp_file_dump="1" 2351 fi 2352 # Temp file 'compress' 2353 _err_tmp_file_comp="" 2354 _ern_tmp_file_comp="0" 2355 if ! _tmp_file_comp="$( create_tmp_file "${_tmp_dir}/.dump_XXXXXXXXXXXXXXX" "0600" 2>/dev/null)"; then 2356 _err_tmp_file_comp="Could not create tmp file ${_tmp_dir}" 2357 _ern_tmp_file_comp="1" 2358 fi 2359 2360 # Set umask prior writing, so we get the correct chmod just at the time of writing to disk 2361 umask "$(chmod_2_umask "${_file_chmod}")"; 2362 2363 # POSIX pipefail emulation 2364 exec 4>&1 2365 # Ignore ${_mysql_arg} to be quoted 2366 # shellcheck disable=SC2086 2367 _error_statuses="$( ( 2368 ( 2369 $(which mysqldump) ${_mysql_arg} "${_database}" 2> "${_tmp_file_dump}"; 2370 printf "%s\n%s\n" \ 2371 "0:$?:$(head -n1 "${_tmp_file_dump}")" \ 2372 "3:${_ern_tmp_file_dump}:${_err_tmp_file_dump}" >&3; 2373 ) | 2374 ( 2375 ${_compress_bin} ${_compress_arg} 2> "${_tmp_file_comp}" > "${_file_name}"; 2376 printf "%s\n%s\n" \ 2377 "1:$?:$(head -n1 "${_tmp_file_comp}")" \ 2378 "4:${_ern_tmp_file_comp}:${_err_tmp_file_comp}" >&3; 2379 ) 2380 ) 3>&1 >&4)" 2381 exec 4>&- 2382 2383 # Delete tmp file 2384 if [ "${_ern_tmp_file_dump}" = "0" ]; then 2385 if [ ! -f "${_tmp_file_dump}" ]; then 2386 _error_statuses="$( printf "${_error_statuses}\n%s\n" "6:1:tmp file does not exist ${_tmp_file_dump}" )" 2387 elif ! rm "${_tmp_file_dump}" 2>/dev/null; then 2388 _error_statuses="$( printf "${_error_statuses}\n%s\n" "6:1:Could not delete tmp file ${_tmp_file_dump}" )" 2389 fi 2390 fi 2391 # Delete tmp file 2392 if [ "${_ern_tmp_file_comp}" = "0" ]; then 2393 if [ ! -f "${_tmp_file_comp}" ]; then 2394 _error_statuses="$( printf "${_error_statuses}\n%s\n" "7:1:tmp file does not exist ${_tmp_file_comp}" )" 2395 elif ! rm "${_tmp_file_comp}" 2>/dev/null; then 2396 _error_statuses="$( printf "${_error_statuses}\n%s\n" "7:1:Could not delete tmp file ${_tmp_file_comp}" )" 2397 fi 2398 fi 2399 2400 2401 # 2402 # 2: Encrypted 2403 # 2404 elif [ "${_dump_mode}" = "2" ]; then 2405 2406 # Temp file 'mysqldump' 2407 _err_tmp_file_dump="" 2408 _ern_tmp_file_dump="0" 2409 if ! _tmp_file_dump="$( create_tmp_file "${_tmp_dir}/.dump_XXXXXXXXXXXXXXX" "0600" 2>/dev/null)"; then 2410 _err_tmp_file_dump="Could not create tmp file ${_tmp_dir}" 2411 _ern_tmp_file_dump="1" 2412 fi 2413 # Temp file 'encrypt' 2414 _err_tmp_file_encr="" 2415 _ern_tmp_file_encr="0" 2416 if ! _tmp_file_encr="$( create_tmp_file "${_tmp_dir}/.dump_XXXXXXXXXXXXXXX" "0600" 2>/dev/null)"; then 2417 _err_tmp_file_encr="Could not create tmp file ${_tmp_dir}" 2418 _ern_tmp_file_encr="1" 2419 fi 2420 2421 # Set umask prior writing, so we get the correct chmod just at the time of writing to disk 2422 umask "$(chmod_2_umask "${_file_chmod}")"; 2423 2424 # POSIX pipefail emulation 2425 exec 4>&1 2426 2427 # Ignore ${_mysql_arg} to be quoted 2428 # shellcheck disable=SC2086 2429 _error_statuses="$( ( 2430 ( 2431 $(which mysqldump) ${_mysql_arg} "${_database}" 2> "${_tmp_file_dump}"; 2432 printf "%s\n%s\n" \ 2433 "0:$?:$(head -n1 "${_tmp_file_dump}")" \ 2434 "3:${_ern_tmp_file_dump}:${_err_tmp_file_dump}" >&3; 2435 2436 ) | 2437 ( 2438 $(which openssl) smime -encrypt -binary -text -outform DER ${_openssl_algo} -out "${_file_name}" "${_openssl_cert}" 2> "${_tmp_file_encr}"; 2439 printf "%s\n%s\n" \ 2440 "2:$?:$(head -n1 "${_tmp_file_encr}")" \ 2441 "5:${_ern_tmp_file_encr}:${_err_tmp_file_encr}" >&3; 2442 ) 2443 2444 ) 3>&1 >&4)" 2445 exec 4>&- 2446 2447 # Delete tmp file 2448 if [ "${_ern_tmp_file_dump}" = "0" ]; then 2449 if [ ! -f "${_tmp_file_dump}" ]; then 2450 _error_statuses="$( printf "${_error_statuses}\n%s\n" "6:1:tmp file does not exist ${_tmp_file_dump}" )" 2451 elif ! rm "${_tmp_file_dump}" 2>/dev/null; then 2452 _error_statuses="$( printf "${_error_statuses}\n%s\n" "6:1:Could not delete tmp file ${_tmp_file_dump}" )" 2453 fi 2454 fi 2455 # Delete tmp file 2456 if [ "${_ern_tmp_file_encr}" = "0" ]; then 2457 if [ ! -f "${_tmp_file_encr}" ]; then 2458 _error_statuses="$( printf "${_error_statuses}\n%s\n" "8:1:tmp file does not exist ${_tmp_file_encr}" )" 2459 elif ! rm "${_tmp_file_encr}" 2>/dev/null; then 2460 _error_statuses="$( printf "${_error_statuses}\n%s\n" "8:1:Could not delete tmp file ${_tmp_file_encr}" )" 2461 fi 2462 fi 2463 2464 2465 # 2466 # 3: Compressed & Encrypted 2467 # 2468 elif [ "${_dump_mode}" = "3" ]; then 2469 2470 # Temp file 'mysqldump' 2471 _err_tmp_file_dump="" 2472 _ern_tmp_file_dump="0" 2473 if ! _tmp_file_dump="$( create_tmp_file "${_tmp_dir}/.dump_XXXXXXXXXXXXXXX" "0600" 2>/dev/null)"; then 2474 _err_tmp_file_dump="Could not create tmp file ${_tmp_dir}" 2475 _ern_tmp_file_dump="1" 2476 fi 2477 # Temp file 'compress' 2478 _err_tmp_file_comp="" 2479 _ern_tmp_file_comp="0" 2480 if ! _tmp_file_comp="$( create_tmp_file "${_tmp_dir}/.dump_XXXXXXXXXXXXXXX" "0600" 2>/dev/null)"; then 2481 _err_tmp_file_comp="Could not create tmp file ${_tmp_dir}" 2482 _ern_tmp_file_comp="1" 2483 fi 2484 # Temp file 'encrypt' 2485 _err_tmp_file_encr="" 2486 _ern_tmp_file_encr="0" 2487 if ! _tmp_file_encr="$( create_tmp_file "${_tmp_dir}/.dump_XXXXXXXXXXXXXXX" "0600" 2>/dev/null)"; then 2488 _err_tmp_file_encr="Could not create tmp file ${_tmp_dir}" 2489 _ern_tmp_file_encr="1" 2490 fi 2491 2492 # Set umask prior writing, so we get the correct chmod just at the time of writing to disk 2493 umask "$(chmod_2_umask "${_file_chmod}")"; 2494 2495 # POSIX pipefail emulation 2496 exec 4>&1 2497 # Ignore ${_mysql_arg} to be quoted 2498 # shellcheck disable=SC2086 2499 _error_statuses="$( ( 2500 ( 2501 $(which mysqldump) ${_mysql_arg} "${_database}" 2> "${_tmp_file_dump}"; 2502 printf "%s\n%s\n" \ 2503 "0:$?:$(head -n1 "${_tmp_file_dump}")" \ 2504 "3:${_ern_tmp_file_dump}:${_err_tmp_file_dump}" >&3; 2505 ) | 2506 ( 2507 ${_compress_bin} ${_compress_arg} 2> "${_tmp_file_comp}"; 2508 printf "%s\n%s\n" \ 2509 "1:$?:$(head -n1 "${_tmp_file_comp}")" \ 2510 "4:${_ern_tmp_file_comp}:${_err_tmp_file_comp}" >&3; 2511 ) | 2512 ( 2513 $(which openssl) smime -encrypt -binary -text -outform DER ${_openssl_algo} -out "${_file_name}" "${_openssl_cert}" 2> "${_tmp_file_encr}"; 2514 printf "%s\n%s\n" \ 2515 "2:$?:$(head -n1 "${_tmp_file_encr}")" \ 2516 "5:${_ern_tmp_file_encr}:${_err_tmp_file_encr}" >&3; 2517 ) 2518 2519 ) 3>&1 >&4)" 2520 exec 4>&- 2521 2522 # Delete tmp file 2523 if [ "${_ern_tmp_file_dump}" = "0" ]; then 2524 if [ ! -f "${_tmp_file_dump}" ]; then 2525 _error_statuses="$( printf "${_error_statuses}\n%s\n" "6:1:tmp file does not exist ${_tmp_file_dump}" )" 2526 elif ! rm "${_tmp_file_dump}" 2>/dev/null; then 2527 _error_statuses="$( printf "${_error_statuses}\n%s\n" "6:1:Could not delete tmp file ${_tmp_file_dump}" )" 2528 fi 2529 fi 2530 # Delete tmp file 2531 if [ "${_ern_tmp_file_comp}" = "0" ]; then 2532 if [ ! -f "${_tmp_file_comp}" ]; then 2533 _error_statuses="$( printf "${_error_statuses}\n%s\n" "7:1:tmp file does not exist ${_tmp_file_comp}" )" 2534 elif ! rm "${_tmp_file_comp}" 2>/dev/null; then 2535 _error_statuses="$( printf "${_error_statuses}\n%s\n" "7:1:Could not delete tmp file ${_tmp_file_comp}" )" 2536 fi 2537 fi 2538 # Delete tmp file 2539 if [ "${_ern_tmp_file_encr}" = "0" ]; then 2540 if [ ! -f "${_tmp_file_encr}" ]; then 2541 _error_statuses="$( printf "${_error_statuses}\n%s\n" "8:1:tmp file does not exist ${_tmp_file_encr}" )" 2542 elif ! rm "${_tmp_file_encr}" 2>/dev/null; then 2543 _error_statuses="$( printf "${_error_statuses}\n%s\n" "8:1:Could not delete tmp file ${_tmp_file_encr}" )" 2544 fi 2545 fi 2546 fi 2547 2548 # Output the error statuses 2549 echo "${_error_statuses}" 2550 return 0 2551} 2552 2553 2554# Evaluate pipefail errors 2555# 2556# @param string Multiline pipefail string 2557# @output string Multiline error messages 2558# @return integer Success 2559mysqldump_pipefail_errors() { 2560 _error_statuses="${1}" 2561 2562 _errors="" 2563 _errno="0" 2564 2565 IFS=' 2566 ' 2567 for _err in ${_error_statuses}; do 2568 _type="$( echo "${_err}" | awk -F ':' '{print $1}' )" 2569 _exit="$( echo "${_err}" | awk -F ':' '{print $2}' )" 2570 _msg="$( echo "${_err}" | awk -F ':' '{for (i=3; i<NF; i++) printf $i " "; print $NF}' )" 2571 2572 # ---- dumping 2573 if [ "${_type}" = "0" ]; then 2574 if [ "${_exit}" != "0" ]; then 2575 [ -z "${_errors}" ] && _errors="mysqldump: ${_msg}" || _errors="$( printf "%s\nmysqldump: %s" "${_errors}" "${_msg}")" 2576 _errno=$((_errno + 1)) 2577 fi 2578 elif [ "${_type}" = "1" ]; then 2579 if [ "${_exit}" != "0" ]; then 2580 [ -z "${_errors}" ] && _errors="compression: ${_msg}" || _errors="$( printf "%s\ncompression: %s" "${_errors}" "${_msg}")" 2581 _errno=$((_errno + 1)) 2582 fi 2583 elif [ "${_type}" = "2" ]; then 2584 if [ "${_exit}" != "0" ]; then 2585 [ -z "${_errors}" ] && _errors="encryption: ${_msg}" || _errors="$( printf "%s\nencryption: %s" "${_errors}" "${_msg}")" 2586 _errno=$((_errno + 1)) 2587 fi 2588 # ---- file creation 2589 elif [ "${_type}" = "3" ]; then 2590 if [ "${_exit}" != "0" ]; then 2591 [ -z "${_errors}" ] && _errors="tmpfile creation: ${_msg}" || _errors="$( printf "%s\ntmpfile creation: %s" "${_errors}" "${_msg}")" 2592 _errno=$((_errno + 1)) 2593 fi 2594 elif [ "${_type}" = "4" ]; then 2595 if [ "${_exit}" != "0" ]; then 2596 [ -z "${_errors}" ] && _errors="tmpfile creation: ${_msg}" || _errors="$( printf "%s\ntmpfile creation: %s" "${_errors}" "${_msg}")" 2597 _errno=$((_errno + 1)) 2598 fi 2599 elif [ "${_type}" = "5" ]; then 2600 if [ "${_exit}" != "0" ]; then 2601 [ -z "${_errors}" ] && _errors="tmpfile creation: ${_msg}" || _errors="$( printf "%s\ntmpfile creation: %s" "${_errors}" "${_msg}")" 2602 _errno=$((_errno + 1)) 2603 fi 2604 # ---- file deletion 2605 elif [ "${_type}" = "6" ]; then 2606 if [ "${_exit}" != "0" ]; then 2607 [ -z "${_errors}" ] && _errors="tmpfile deletion: ${_msg}" || _errors="$( printf "%s\ntmpfile deletion: %s" "${_errors}" "${_msg}")" 2608 _errno=$((_errno + 1)) 2609 fi 2610 elif [ "${_type}" = "7" ]; then 2611 if [ "${_exit}" != "0" ]; then 2612 [ -z "${_errors}" ] && _errors="tmpfile deletion: ${_msg}" || _errors="$( printf "%s\ntmpfile deletion: %s" "${_errors}" "${_msg}")" 2613 _errno=$((_errno + 1)) 2614 fi 2615 elif [ "${_type}" = "8" ]; then 2616 if [ "${_exit}" != "0" ]; then 2617 [ -z "${_errors}" ] && _errors="tmpfile deletion: ${_msg}" || _errors="$( printf "%s\ntmpfile deletion: %s" "${_errors}" "${_msg}")" 2618 _errno=$((_errno + 1)) 2619 fi 2620 fi 2621 done 2622 unset IFS 2623 2624 echo "${_errors}" 2625 return ${_errno} 2626} 2627 2628# Evaluate pipefail warnings 2629# 2630# @param string Multiline pipefail string 2631# @output string Multiline warning messages 2632# @return integer Success 2633mysqldump_pipefail_warnings() { 2634 _error_statuses="${1}" 2635 2636 _warnings="" 2637 _errno="0" 2638 2639 IFS=' 2640 ' 2641 for _err in ${_error_statuses}; do 2642 _type="$( echo "${_err}" | awk -F ':' '{print $1}' )" 2643 _exit="$( echo "${_err}" | awk -F ':' '{print $2}' )" 2644 _msg="$( echo "${_err}" | awk -F ':' '{for (i=3; i<NF; i++) printf $i " "; print $NF}' )" 2645 2646 # ---- dumping 2647 if [ "${_type}" = "0" ]; then 2648 if [ "${_exit}" = "0" ] && [ "${_msg}" != "" ]; then 2649 [ -z "${_warnings}" ] && _warnings="mysqldump: ${_msg}" || _warnings="$( printf "%s\nmysqldump: %s" "${_warnings}" "${_msg}")" 2650 _errno=$((_errno + 1)) 2651 fi 2652 elif [ "${_type}" = "1" ]; then 2653 if [ "${_exit}" = "0" ] && [ "${_msg}" != "" ]; then 2654 [ -z "${_warnings}" ] && _warnings="compression: ${_msg}" || _warnings="$( printf "%s\ncompression: %s" "${_warnings}" "${_msg}")" 2655 _errno=$((_errno + 1)) 2656 fi 2657 elif [ "${_type}" = "2" ]; then 2658 if [ "${_exit}" = "0" ] && [ "${_msg}" != "" ]; then 2659 [ -z "${_warnings}" ] && _warnings="encryption: ${_msg}" || _warnings="$( printf "%s\nencryption: %s" "${_warnings}" "${_msg}")" 2660 _errno=$((_errno + 1)) 2661 fi 2662 # ---- file creation 2663 elif [ "${_type}" = "3" ]; then 2664 if [ "${_exit}" = "0" ] && [ "${_msg}" != "" ]; then 2665 [ -z "${_warnings}" ] && _warnings="tmpfile creation: ${_msg}" || _warnings="$( printf "%s\ntmpfile creation: %s" "${_warnings}" "${_msg}")" 2666 _errno=$((_errno + 1)) 2667 fi 2668 elif [ "${_type}" = "4" ]; then 2669 if [ "${_exit}" = "0" ] && [ "${_msg}" != "" ]; then 2670 [ -z "${_warnings}" ] && _warnings="tmpfile creation: ${_msg}" || _warnings="$( printf "%s\ntmpfile creation: %s" "${_warnings}" "${_msg}")" 2671 _errno=$((_errno + 1)) 2672 fi 2673 elif [ "${_type}" = "5" ]; then 2674 if [ "${_exit}" = "0" ] && [ "${_msg}" != "" ]; then 2675 [ -z "${_warnings}" ] && _warnings="tmpfile creation: ${_msg}" || _warnings="$( printf "%s\ntmpfile creation: %s" "${_warnings}" "${_msg}")" 2676 _errno=$((_errno + 1)) 2677 fi 2678 # ---- file deletion 2679 elif [ "${_type}" = "6" ]; then 2680 if [ "${_exit}" = "0" ] && [ "${_msg}" != "" ]; then 2681 [ -z "${_warnings}" ] && _warnings="tmpfile deletion: ${_msg}" || _warnings="$( printf "%s\ntmpfile deletion: %s" "${_warnings}" "${_msg}")" 2682 _errno=$((_errno + 1)) 2683 fi 2684 elif [ "${_type}" = "7" ]; then 2685 if [ "${_exit}" = "0" ] && [ "${_msg}" != "" ]; then 2686 [ -z "${_warnings}" ] && _warnings="tmpfile deletion: ${_msg}" || _warnings="$( printf "%s\ntmpfile deletion: %s" "${_warnings}" "${_msg}")" 2687 _errno=$((_errno + 1)) 2688 fi 2689 elif [ "${_type}" = "8" ]; then 2690 if [ "${_exit}" = "0" ] && [ "${_msg}" != "" ]; then 2691 [ -z "${_warnings}" ] && _warnings="tmpfile deletion: ${_msg}" || _warnings="$( printf "%s\ntmpfile deletion: %s" "${_warnings}" "${_msg}")" 2692 _errno=$((_errno + 1)) 2693 fi 2694 fi 2695 done 2696 unset IFS 2697 2698 echo "${_warnings}" 2699 return ${_errno} 2700} 2701 2702 2703 2704# 2705# Write the database dump info file with lot's of 2706# useful information. 2707# 2708write_info_file() { 2709 # File arguments 2710 _file_path="${1}" 2711 _file_name="${2}" 2712 _file_chmod="${3}" 2713 # Database arguments 2714 _db_name="${4}" 2715 _db_size="${5}" 2716 _db_tbl_cnt="${6}" 2717 _db_dump_args="${7}" 2718 _db_dump_time="${8}" 2719 # Compression arguments 2720 _compress_opt="${9}" 2721 _compress_bin="${10}" 2722 _compress_arg="${11}" 2723 # Encryption arguments 2724 _encrypt_opt="${12}" 2725 _encrypt_alg="${13}" 2726 _encrypt_pem="${14}" 2727 # MySQL arguments 2728 _mysql_args="${15}" 2729 _mysql_ssl_opt="${16}" 2730 _mysql_ssl_status="${17}" 2731 # MySQL Server Info arguments 2732 _mysql_server_status="${18}" 2733 _mysql_host="${19}" 2734 _mysql_port="${20}" 2735 _mysql_repl_type="${21}" 2736 _mysql_server="${22}" 2737 _mysql_version="${23}" 2738 2739 2740 _mtime="$( get_file_mtime "${_file_path}/${_file_name}" )" 2741 _mtime_h="$( formatted_timestamp "${_mtime}" "%Y-%m-%d %H:%M:%S %Z [%z]" )" 2742 2743 _db_size_kb="$( div "${_db_size}" "1024" )" 2744 _db_size_mb="$( div "${_db_size_kb}" "1024" )" 2745 _db_size_mb="$( round "${_db_size_mb}" "2" )" 2746 2747 # 2748 # Set umask prior writing. 2749 # (Use the same chmod as the dumps itself) 2750 # 2751 umask "$(chmod_2_umask "${_file_chmod}")"; 2752 2753 # Create file 2754 { 2755 echo "; ${INFO_NAME} backup record"; 2756 echo "; Do not alter this file!"; 2757 echo "; Creation of this file can be turned off via config file."; 2758 echo; 2759 echo "; ============================================================"; 2760 echo "; = Local system information"; 2761 echo "; ============================================================"; 2762 echo "[${INFO_NAME}]"; 2763 echo "version = $( which ${INFO_NAME} ) (${INFO_VERSION})"; 2764 echo "vdate = ${INFO_DATE}"; 2765 echo "config = ${CONFIG_FILE}"; 2766 echo; 2767 echo "[system]"; 2768 echo "uname = $( uname -sr )"; 2769 echo "hostname = $( hostname )"; 2770 echo "user = $( whoami )"; 2771 echo "group = $( id -g -n )"; 2772 echo; 2773 echo "[tools]"; 2774 echo "mysqldump = $( which mysqldump ) $( _get_version "mysqldump" )"; 2775 echo "mysql = $( which mysql ) $( _get_version "mysql" )"; 2776 echo "compressor = $(if [ "${_compress_opt}" = "1" ]; then echo "$( which "${_compress_bin}" ) $( _get_version "${_compress_bin}" )"; else echo "Not used"; fi)"; 2777 echo "encryptor = $(if [ "${_encrypt_opt}" = "1" ]; then echo "$( which openssl ) $( _get_version "openssl" )"; else echo "Not used"; fi)"; 2778 echo; 2779 echo "; ============================================================"; 2780 echo "; = Database / File information"; 2781 echo "; ============================================================"; 2782 echo "[database]"; 2783 echo "db_name = ${_db_name}"; 2784 echo "db_size = ${_db_size} Bytes (${_db_size_mb} MB)"; 2785 echo "tbl_cnt = ${_db_tbl_cnt}"; 2786 echo; 2787 echo "[file]"; 2788 echo "file_path = ${_file_path}"; 2789 echo "file_name = ${_file_name}"; 2790 echo "file_size = $( get_file_size "${_file_path}/${_file_name}" "b" ) Bytes ($( get_file_size "${_file_path}/${_file_name}" "m" ) MB)"; 2791 echo "file_chmod = $( get_file_chmod "${_file_path}/${_file_name}" )"; 2792 echo "file_owner = $( get_file_owner "${_file_path}/${_file_name}" )"; 2793 echo "file_group = $( get_file_group "${_file_path}/${_file_name}" )"; 2794 echo "file_mtime = ${_mtime} (${_mtime_h})"; 2795 echo "file_md5 = $( get_file_hash "${_file_path}/${_file_name}" "md5" )"; 2796 echo "file_sha = $( get_file_hash "${_file_path}/${_file_name}" "sha256" )"; 2797 echo; 2798 echo "; ============================================================"; 2799 echo "; = Dump procedure information"; 2800 echo "; ============================================================"; 2801 echo "[mysqldump]"; 2802 echo "encrypted = ${_encrypt_opt}"; 2803 echo "compressed = ${_compress_opt}"; 2804 echo "arguments = ${_db_dump_args}"; 2805 echo "duration = ${_db_dump_time} sec" 2806 echo; 2807 echo "[compression]"; 2808 echo "compressor = $(if [ "${_compress_opt}" = "1" ]; then echo "${_compress_bin}"; fi)"; 2809 echo "arguments = $(if [ "${_compress_opt}" = "1" ]; then echo "${_compress_arg}"; fi)"; 2810 echo; 2811 echo "[encryption]"; 2812 echo "encryptor = $(if [ "${_encrypt_opt}" = "1" ]; then echo "openssl"; fi)"; 2813 echo "algorithm = $(if [ "${_encrypt_opt}" = "1" ]; then echo "${_encrypt_alg}"; fi)"; 2814 echo "pubkey = $(if [ "${_encrypt_opt}" = "1" ]; then echo "${_encrypt_pem}"; fi)"; 2815 echo; 2816 echo "; ============================================================"; 2817 echo "; = Server information"; 2818 echo "; ============================================================"; 2819 echo "[connection]"; 2820 echo "protocol = $( get_mysql_connection_type_info "${_mysql_server_status}" )"; 2821 echo "secured = $(if [ "${_mysql_ssl_opt}" = "1" ]; then echo "SSL: ${_mysql_ssl_status}"; else echo "No SSL"; fi )"; 2822 echo "arguments = ${_mysql_args}"; 2823 echo; 2824 echo "[server]"; 2825 echo "hostname = ${_mysql_host}"; 2826 echo "port = ${_mysql_port}"; 2827 echo "replica = ${_mysql_repl_type}"; 2828 echo "version = $(if [ "${_mysql_server}" != "" ]; then echo "${_mysql_server} ";fi)${_mysql_version}"; 2829 echo; 2830 } 2>/dev/null > "${_file_path}/${_file_name}.info" 2831 2832 _exit="$?" 2833 2834 return ${_exit} 2835} 2836 2837 2838 2839################################################################################ 2840# 2841# M I S C F U N CT I O N S 2842# 2843################################################################################ 2844 2845# 2846# Get version information of certain binaries 2847# 2848# @param string binary 2849# @output string Detailed version information 2850# @return integer Success 2851_get_version() { 2852 _tool="${1}" 2853 2854 _version="" 2855 _extra="" 2856 _exit=0 2857 2858 if [ "${_tool}" = "mysqldump" ]; then 2859 _version="$( $(which mysqldump) --version | sed 's/.*mysqldump[[:space:]]*Ver[[:space:]]*//' | awk -F ',' '{print $1}' )" 2860 _extra="$( $(which mysqldump) --version | sed 's/.*mysqldump[[:space:]]*Ver[[:space:]]*//' | awk -F ',' '{print $2}' | sed 's/^[[:space:]]*//g' )" 2861 elif [ "${_tool}" = "mysql" ]; then 2862 _version="$( $(which mysql) --version | sed 's/.*mysql[[:space:]]*Ver[[:space:]]*//' | awk -F ',' '{print $1}' )" 2863 _extra="$( $(which mysql) --version | sed 's/.*mysql[[:space:]]*Ver[[:space:]]*//' | awk -F ',' '{print $2}' | sed 's/^[[:space:]]*//g' )" 2864 elif [ "${_tool}" = "openssl" ]; then 2865 _version="$( $(which openssl) version | sed 's/^OpenSSL[[:space:]]*//' )" 2866 _extra="" 2867 elif [ "${_tool}" = "tmpwatch" ]; then 2868 _version="$( $(which tmpwatch) --version 2>&1 | grep -oE 'tmpwatch[[:space:]]+[0-9.]+' | sed 's/tmpwatch[[:space:]]//' )" 2869 _extra="" 2870 elif [ "${_tool}" = "tmpreaper" ]; then 2871 _version="$( $(which tmpreaper) --version 2>&1 | grep -oiE 'tmpreaper.*version.*[0-9.]+' | sed 's/.*Version:[[:space:]]//' )" 2872 _extra="" 2873 elif [ "${_tool}" = "gzip" ]; then 2874 _version="$( $(which gzip) --version 2>&1 | head -n1 )" 2875 _extra="" 2876 elif [ "${_tool}" = "bzip2" ]; then 2877 _version="$( $(which bzip2) --help 2>&1 | head -n1 | sed 's/.*Version[[:space:]]*//' )" 2878 _extra="" 2879 else 2880 _version="Unable to obtain version" 2881 _exit=1 2882 fi 2883 2884 if [ "${_extra}" != "" ]; then 2885 echo "(${_version}) [${_extra}]" 2886 else 2887 echo "(${_version})" 2888 fi 2889 2890 return ${_exit} 2891} 2892 2893 2894 2895 2896################################################################################ 2897# 2898# U S A G E F U N CT I O N S 2899# 2900################################################################################ 2901 2902 2903 2904############################################################ 2905# Usage/Help/Version 2906############################################################ 2907 2908# 2909# Usage 2910# 2911print_usage() { 2912# printf "%s %s %s\n" "Usage:" "${INFO_NAME}" "[--conf] [--cnf] [--cron] [-v[v]] [--test] [--info] [--help] [--version]" 2913 printf "%s %s %s\n" "Usage:" "${INFO_NAME}" "[--conf] [--cron] [--test] [-v[v]]" 2914# printf "%s %s %s\n" " " "${INFO_NAME}" "--info" 2915 printf "%s %s %s\n" " " "${INFO_NAME}" "--help" 2916 printf "%s %s %s\n" " " "${INFO_NAME}" "--version" 2917} 2918 2919# 2920# Display program usage 2921# 2922print_help() { 2923 2924 print_usage 2925 echo 2926 echo "When invoked without any arguments, it will start dumping databases as" 2927 echo "defined in mysqldump-secure.conf." 2928 echo 2929 echo " --conf Pass a different configuration file than the default one." 2930 echo " E.g.: --conf=/etc/mysqldump-secure-alt.conf" 2931 echo 2932# echo " --cnf Pass different mysql cnf credentials file than the default one." 2933# echo " E.g.: --cnf=/etc/mysqldump-secure-slave.cnf" 2934# echo 2935 echo " --cron Use for cron run. It will only output errors and warnings" 2936 echo " and will silence all info, debug and trace output." 2937 echo 2938 echo " --test Test requirements and exit." 2939 echo " Combine with -v or -vv for more verbose output." 2940 echo 2941 echo " -v Show debug output." 2942 echo " Can be combined with --conf and --test" 2943 echo 2944 echo " -vv Show debug and trace output." 2945 echo " Can be combined with --conf and --test" 2946 echo 2947# echo " --info Show settings and exit." 2948# echo 2949 echo " --help Show this help screen." 2950 echo 2951 echo " --version Show version information." 2952 echo 2953 echo 2954 echo "Exit codes" 2955 echo 2956 echo " 0 All fine, no fatals, no errors and no warnings occured." 2957 echo " 1 Warnings occured, but all dumps were successfull." 2958 echo " 2 Errors occured, but all dumps were successfull." 2959 echo " 3 Failed. Mysqldump encountered errors." 2960 echo " 4 Abort. The program aborted, due to missing requirements," 2961 echo " wrong arguments or a misconfiguration." 2962 echo 2963 echo "Further reading" 2964 echo 2965 echo "See 'man mysqldump-secure' for more help." 2966 echo "Visist http://mysqldump-secure.org and browse documentation." 2967} 2968# TODO: 2969# -------- 2970# --info Shows current configuration and paths 2971# --cli Start interactive cli (mysqldump-secure-cli) to show dumps, import dumps, set configs, etc 2972 2973 2974 2975# 2976# Display program version and credits 2977# 2978print_version() { 2979 printf "Name: %s\n" "${INFO_NAME}" 2980 printf "Version: %s (%s)\n" "${INFO_VERSION}" "${INFO_DATE}" 2981 printf "Author: %s (%s)\n" "${INFO_AUTHOR}" "${INFO_GPGKEY}" 2982 printf "Code: %s\n" "${INFO_REPO}" 2983 printf "URL: %s\n" "${INFO_URL}" 2984 printf "License: %s\n" "${INFO_LICENSE}" 2985} 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995#################################################################################################### 2996#################################################################################################### 2997## 2998## M A I N E N T R Y P O I N T ( A R G U M E N T S ) 2999## 3000#################################################################################################### 3001#################################################################################################### 3002 3003 3004 3005################################################################################ 3006# 3007# COMMAND LINE ARGUMENTS 3008# 3009################################################################################ 3010 3011############################################################ 3012# 1.) Evaluate cmd arguments 3013############################################################ 3014 3015 3016_ARG_CONF="0" # Different config file specified? 3017_ARG_VERB="1" # Verbose mode? 3018_ARG_CRON="0" # Cron mode? 3019_ARG_TEST="0" # Test mode? 3020_ARG_HELP="0" # Show help? 3021_ARG_VERS="0" # Show version? 3022 3023_CUS_CONF="" # Where is the custom config? 3024#_ARG_INFO="0" 3025 3026 3027# 3028# Loop over command line arguments 3029# 3030while [ $# -gt 0 ]; do 3031 case "$1" in 3032 3033 --conf=*) 3034 if [ "${_ARG_HELP}" = "1" ] || [ "${_ARG_VERS}" = "1" ]; then 3035 echo "Invalid. Arguments cannot be mixed." 1>&2 3036 echo "Type '${INFO_NAME} --help' for available options." 1>&2 3037 exit $EXIT_ABORT 3038 fi 3039 if [ "${_ARG_CONF}" != "0" ]; then 3040 echo "Invalid. Argument '--conf' already specified." 1>&2 3041 echo "Type '${INFO_NAME} --help' for available options." 1>&2 3042 exit $EXIT_ABORT 3043 fi 3044 _ARG_CONF="1" 3045 _CUS_CONF="$(echo "$1" | sed 's/--conf=//g')" 3046 ;; 3047 3048 3049 -v) 3050 if [ "${_ARG_HELP}" = "1" ] || [ "${_ARG_VERS}" = "1" ] || [ "${_ARG_CRON}" = "1" ]; then 3051 echo "Invalid. Arguments cannot be mixed." 1>&2 3052 echo "Type '${INFO_NAME} --help' for available options." 1>&2 3053 exit $EXIT_ABORT 3054 fi 3055 if [ "${_ARG_VERB}" != "1" ]; then 3056 echo "Invalid. Argument '-v' already specified (use -vv for more verbosity)." 1>&2 3057 echo "Type '${INFO_NAME} --help' for available options." 1>&2 3058 exit $EXIT_ABORT 3059 fi 3060 _ARG_VERB="2" 3061 ;; 3062 3063 3064 -vv) 3065 if [ "${_ARG_HELP}" = "1" ] || [ "${_ARG_VERS}" = "1" ] || [ "${_ARG_CRON}" = "1" ]; then 3066 echo "Invalid. Arguments cannot be mixed." 1>&2 3067 echo "Type '${INFO_NAME} --help' for available options." 1>&2 3068 exit $EXIT_ABORT 3069 fi 3070 if [ "${_ARG_VERB}" != "1" ]; then 3071 echo "Invalid. Argument '-v' already specified (use -vv for more verbosity)." 1>&2 3072 echo "Type '${INFO_NAME} --help' for available options." 1>&2 3073 exit $EXIT_ABORT 3074 fi 3075 _ARG_VERB="3" 3076 ;; 3077 3078 3079 --cron) 3080 if [ "${_ARG_TEST}" = "1" ] || [ "${_ARG_HELP}" = "1" ] || [ "${_ARG_VERS}" = "1" ] || [ "${_ARG_VERB}" != "1" ]; then 3081 echo "Invalid. Arguments cannot be mixed." 1>&2 3082 echo "Type '${INFO_NAME} --help' for available options." 1>&2 3083 exit $EXIT_ABORT 3084 fi 3085 if [ "${_ARG_CRON}" != "0" ]; then 3086 echo "Invalid. Argument '--cron' already specified." 1>&2 3087 echo "Type '${INFO_NAME} --help' for available options." 1>&2 3088 exit $EXIT_ABORT 3089 fi 3090 _ARG_CRON="1" 3091 ;; 3092 3093 3094 --test) 3095 if [ "${_ARG_CRON}" = "1" ] || [ "${_ARG_HELP}" = "1" ] || [ "${_ARG_VERS}" = "1" ]; then 3096 echo "Invalid. Arguments cannot be mixed." 1>&2 3097 echo "Type '${INFO_NAME} --help' for available options." 1>&2 3098 exit $EXIT_ABORT 3099 fi 3100 if [ "${_ARG_TEST}" != "0" ]; then 3101 echo "Invalid. Argument '--test' already specified." 1>&2 3102 echo "Type '${INFO_NAME} --help' for available options." 1>&2 3103 exit $EXIT_ABORT 3104 fi 3105 _ARG_TEST="1" 3106 ;; 3107 3108# --info) 3109# _ARG_INFO="1" 3110# ;; 3111 3112 3113 --help) 3114 if [ "${_ARG_CONF}" = "1" ] || [ "${_ARG_CRON}" = "1" ] || [ "${_ARG_TEST}" = "1" ] || [ "${_ARG_VERS}" = "1" ] || [ "${_ARG_VERB}" != "1" ]; then 3115 echo "Invalid. Arguments cannot be mixed." 1>&2 3116 echo "Type '${INFO_NAME} --help' for available options." 1>&2 3117 exit $EXIT_ABORT 3118 fi 3119 if [ "${_ARG_HELP}" != "0" ]; then 3120 echo "Invalid. Argument '--help' already specified." 1>&2 3121 echo "Type '${INFO_NAME} --help' for available options." 1>&2 3122 exit $EXIT_ABORT 3123 fi 3124 _ARG_HELP="1" 3125 print_help 3126 exit 0 3127 ;; 3128 3129 3130 --version) 3131 if [ "${_ARG_CONF}" = "1" ] || [ "${_ARG_CRON}" = "1" ] || [ "${_ARG_TEST}" = "1" ] || [ "${_ARG_HELP}" = "1" ] || [ "${_ARG_VERB}" != "1" ]; then 3132 echo "Invalid. Arguments cannot be mixed." 1>&2 3133 echo "Type '${INFO_NAME} --help' for available options." 1>&2 3134 exit $EXIT_ABORT 3135 fi 3136 if [ "${_ARG_VERS}" != "0" ]; then 3137 echo "Invalid. Argument '--versopm' already specified." 1>&2 3138 echo "Type '${INFO_NAME} --help' for available options." 1>&2 3139 exit $EXIT_ABORT 3140 fi 3141 _ARG_VERS="1" 3142 print_version 3143 exit 0 3144 ;; 3145 3146 3147 *) 3148 echo "Invalid argument: '${1}'." 1>&2 3149 echo "Type '${INFO_NAME} --help' for available options." 1>&2 3150 exit $EXIT_ABORT 3151 ;; 3152 3153 esac 3154 shift 3155done 3156 3157 3158# 3159# Set output verbosity 3160# 3161if [ "${_ARG_CRON}" = "1" ]; then 3162 OUT_VERBOSITY="0" # only show fatals, errors and warnings 3163else 3164 OUT_VERBOSITY="${_ARG_VERB}" # 1, 2 or 3 3165fi 3166 3167 3168# 3169# Set file verbosity (default is off) 3170# 3171LOG_VERBOSITY="0" 3172 3173 3174# 3175# Use default config or user specified config file 3176# 3177if [ -z "${_CUS_CONF-}" ]; then 3178 CONFIG_FILE="${_DEFAULT_CONFIG_FILE}" 3179else 3180 CONFIG_FILE="${_CUS_CONF}" 3181fi 3182 3183 3184############################################################ 3185# 2.) Validate config file location/rights 3186############################################################ 3187 3188if [ ! -f "${CONFIG_FILE}" ]; then 3189 debug "fatal" "(RUN): Configuration file not found in ${CONFIG_FILE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3190 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3191 exit $EXIT_ABORT 3192fi 3193if [ -L "${CONFIG_FILE}" ]; then 3194 if _TMP="$(get_file_realpath "${CONFIG_FILE}")" >/dev/null 2>&1; then 3195 debug "trace" "(RUN): \$CONFIG_FILE is a symlink. Setting target to: ${_TMP}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3196 CONFIG_FILE="${_TMP}" 3197 else 3198 debug "fatal" "(RUN): Cannot resolve symlink of: $CONFIG_FILE" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3199 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3200 exit $EXIT_ABORT 3201 fi 3202fi 3203if [ ! -r "${CONFIG_FILE}" ]; then 3204 debug "fatal" "(RUN): Configuration file is not readable in ${CONFIG_FILE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3205 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3206 exit $EXIT_ABORT 3207fi 3208if ! compare_chmod "$(get_file_chmod "${CONFIG_FILE}")" "${_DEFAULT_CONFIG_CHMOD}" > /dev/null 2>&1 ; then 3209 debug "warn" "(RUN): Configuration file ${CONFIG_FILE} has dangerous permissions: $(get_file_chmod "${CONFIG_FILE}"), should be: ${_DEFAULT_CONFIG_CHMOD}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3210 debug_pi "warn" "(RUN): Trying to chmod to ${_DEFAULT_CONFIG_CHMOD}..." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3211 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3212 3213 if ! chmod ${_DEFAULT_CONFIG_CHMOD} "${CONFIG_FILE}" > /dev/null 2>&1 ; then 3214 debug_i "fatal" "Failed\n" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3215 debug "fatal" "Failed to chmod ${CONFIG_FILE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3216 debug "fatal" "Fix it manually to ${_DEFAULT_CONFIG_CHMOD}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3217 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3218 exit $EXIT_ABORT 3219 else 3220 debug_i "warn" "OK\n" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3221 fi 3222fi 3223 3224 3225 3226# Read config file 3227# Comment required by shellcheck, 3228# See problem here: https://github.com/koalaman/shellcheck/wiki/SC1090 3229# shellcheck disable=SC1090 3230# 3231# TODO: Manually parse the file via sed or awk to be safer 3232. "${CONFIG_FILE}" 3233 3234 3235 3236 3237 3238 3239 3240#################################################################################################### 3241#################################################################################################### 3242## 3243## M A I N E N T R Y P O I N T ( E R R O R C H E C K I N G ) 3244## 3245#################################################################################################### 3246#################################################################################################### 3247 3248 3249 3250 3251################################################################################ 3252# 3253# EVALUATE CONFIG FILE 3254# 3255################################################################################ 3256 3257 3258############################################################ 3259# Logging Options 3260############################################################ 3261 3262# Be really strict on checking if we are going to log to file 3263# or not. Also make sure that the logfile is writeable and 3264# that no other has read permissions to the file. 3265if ! set | grep '^LOG=' >/dev/null 2>&1; then 3266 debug "warn" "(CFG): \$LOG variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3267 debug "warn" "(OPT): Logging disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3268 LOG=0 3269 LOG_FILE="" 3270 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3271elif [ -z "${LOG}" ]; then 3272 debug "warn" "(CFG): \$LOG variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3273 debug "warn" "(OPT): Logging disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3274 LOG=0 3275 LOG_FILE="" 3276 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3277elif [ "${LOG}" = "1" ] || [ "${LOG}" = "2" ] || [ "${LOG}" = "3" ]; then 3278 3279 # Check chmod variable 3280 if ! set | grep '^LOG_CHMOD=' >/dev/null 2>&1; then 3281 debug "warn" "(CFG): \$LOG_CHMOD variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3282 debug "warn" "(CFG): Setting default to: ${_DEFAULT_LOG_CHMOD}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3283 LOG_CHMOD="${_DEFAULT_LOG_CHMOD}" 3284 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3285 elif [ -z "${LOG_CHMOD}" ]; then 3286 debug "warn" "(CFG): \$LOG_CHMOD variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3287 debug "warn" "(CFG): Setting default to: ${_DEFAULT_LOG_CHMOD}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3288 LOG_CHMOD="${_DEFAULT_LOG_CHMOD}" 3289 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3290 elif ! valid_chmod "${LOG_CHMOD}" > /dev/null 2>&1; then 3291 debug "warn" "(CFG): Invalid value for \$LOG_CHMOD: ${LOG_CHMOD}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3292 debug "warn" "(CFG): Setting default to: ${_DEFAULT_LOG_CHMOD}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3293 LOG_CHMOD="${_DEFAULT_LOG_CHMOD}" 3294 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3295 fi 3296 3297 # Check logfile variable 3298 if ! set | grep '^LOG_FILE=' >/dev/null 2>&1; then 3299 debug "warn" "(CFG): \$LOG_FILE variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3300 debug "warn" "(OPT): Setting default to: ${_DEFAULT_LOG_FILE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3301 LOG_FILE="${_DEFAULT_LOG_FILE}" 3302 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3303 elif [ -z "${LOG_FILE}" ]; then 3304 debug "warn" "(CFG): \$LOG_FILE variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3305 debug "warn" "(OPT): Setting default to: ${_DEFAULT_LOG_FILE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3306 LOG_FILE="${_DEFAULT_LOG_FILE}" 3307 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3308 fi 3309 3310 # Resolve symlink? 3311 if [ -L "${LOG_FILE}" ]; then 3312 if _TMP="$(get_file_realpath "${LOG_FILE}")" >/dev/null 2>&1; then 3313 debug "trace" "(RUN): \$LOG_FILE is a symlink. Setting target to: ${_TMP}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3314 LOG_FILE="${_TMP}" 3315 else 3316 debug "err" "(RUN): Cannot resolve symlink of: $LOG_FILE" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3317 debug "err" "(OPT): Logging disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3318 LOG=0 3319 MDS_ERROR_COUNT=$((MDS_ERROR_COUNT + 1)) 3320 fi 3321 fi 3322 3323 # Check if logfile exists 3324 if [ ! -f "${LOG_FILE}" ]; then 3325 # Check if logging directory exists 3326 if [ ! -d "$(dirname "${LOG_FILE}")" ]; then 3327 debug "warn" "(RUN): Log directory does not exist in $(dirname "${LOG_FILE}")" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3328 debug_pi "warn" "(RUN): Trying to create..." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3329 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3330 if ! mkdir -p "$(dirname "${LOG_FILE}")" > /dev/null 2>&1 ; then 3331 debug_i "err" "Failed\n" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3332 debug "err" "(RUN): Failed to create directoy: $(dirname "${LOG_FILE}")" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3333 debug "err" "(OPT): Logging disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3334 LOG=0 3335 MDS_ERROR_COUNT=$((MDS_ERROR_COUNT + 1)) 3336 else 3337 debug_i "warn" "OK\n" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3338 fi 3339 fi 3340 # If logging is still OK (dir exists), check if the file can be created 3341 if [ "${LOG}" != "0" ]; then 3342 debug "warn" "(RUN): Log file does not exist in ${LOG_FILE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3343 debug_pi "warn" "(RUN): Trying to create..." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3344 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3345 3346 if ! touch "${LOG_FILE}" > /dev/null 2>&1 ; then 3347 debug_i "err" "Failed\n" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3348 debug "err" "(RUN): Failed to create file: ${LOG_FILE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3349 debug "err" "(OPT): Logging disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3350 LOG=0 3351 MDS_ERROR_COUNT=$((MDS_ERROR_COUNT + 1)) 3352 else 3353 debug_i "warn" "OK\n" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3354 fi 3355 fi 3356 fi 3357 3358 # Logging still on? 3359 # Check for permissions 3360 if [ "${LOG}" != "0" ]; then 3361 if ! compare_chmod "$(get_file_chmod "${LOG_FILE}")" "${LOG_CHMOD}" > /dev/null 2>&1 ; then 3362 debug "warn" "(RUN): Log file has wrong permissions: $(get_file_chmod "${LOG_FILE}"), should be: ${LOG_CHMOD}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3363 debug_pi "warn" "(RUN): Trying to chmod to ${LOG_CHMOD}..." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3364 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3365 3366 if ! chmod ${LOG_CHMOD} "${LOG_FILE}" > /dev/null 2>&1 ; then 3367 debug_i "err" "Failed\n" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3368 debug "err" "(RUN): Failed to chmod ${LOG_CHMOD} ${LOG_FILE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3369 debug "err" "(OPT): Logging disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3370 LOG=0 3371 MDS_ERROR_COUNT=$((MDS_ERROR_COUNT + 1)) 3372 else 3373 debug_i "warn" "OK\n" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3374 fi 3375 fi 3376 fi 3377 3378 # Logging still on? 3379 # Check if it is writeable 3380 if [ "${LOG}" != "0" ]; then 3381 3382 # Logfile not writeable 3383 if [ ! -w "${LOG_FILE}" ]; then 3384 debug "err" "(RUN): Log file ${LOG_FILE} not writeable. Check \$LOG_CHMOD value inf config." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3385 debug "err" "(OPT): Logging disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3386 LOG=0 3387 MDS_ERROR_COUNT=$((MDS_ERROR_COUNT + 1)) 3388 fi 3389 fi 3390elif [ "${LOG}" = "0" ]; then 3391 debug "info" "(OPT): Logging disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3392 LOG_FILE="" 3393else 3394 debug "warn" "(CFG): Invalid value for \$LOG: ${LOG}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3395 debug "warn" "(OPT): Logging disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "" 3396 LOG=0 3397 LOG_FILE="" 3398 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3399fi 3400 3401# Is logging still enabled after all checks? 3402# Write to the file 3403if [ "${LOG}" != "0" ]; then 3404 3405 # Assign new value for logging verbosity 3406 LOG_VERBOSITY="${LOG}" 3407 3408 { 3409 echo; 3410 echo "--------------------------------------------------------------------------------"; 3411 echo "$(date '+%Y-%m-%d') $(date '+%H:%M:%S') Starting"; 3412 } >> "${LOG_FILE}" 3413 debug "debug" "(CFG): Using config: ${CONFIG_FILE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3414 debug "info" "(OPT): Logging enabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3415 debug "debug" "(OPT): Log level: ${LOG}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3416 debug "debug" "(OPT): Log file: ${LOG_FILE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3417else 3418 debug "debug" "(CFG): Using config: ${CONFIG_FILE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3419fi 3420 3421 3422 3423 3424 3425############################################################ 3426# Command line arguments 3427############################################################ 3428if [ "${_ARG_CRON}" = "1" ]; then 3429 # Note: This will never be outputted to stdout/stderr (only to logfile) 3430 debug "trace" "(ARG): Running in cron mode (--cron)." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3431fi 3432if [ "${_ARG_TEST}" = "1" ]; then 3433 debug "info" "(ARG): Running in test mode (--test)." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3434fi 3435if [ "${_ARG_VERB}" = "1" ]; then 3436 debug "trace" "(ARG): Running in verbose mode (--verbose)." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3437fi 3438#if [ "${_ARG_INFO}" = "1" ]; then 3439# debug "info" "Showing information only (--info)." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3440#fi 3441 3442 3443 3444############################################################ 3445# Tmp folder 3446############################################################ 3447 3448 3449# Check if mktemp exits 3450if ! command -v mktemp > /dev/null 2>&1 ; then 3451 debug "fatal" "(RUN): 'mktemp' not found" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3452 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3453 exit $EXIT_ABORT 3454fi 3455 3456# Check $TMP_DIR variable 3457if ! set | grep '^TMP_DIR=' >/dev/null 2>&1; then 3458 debug "warn" "(CFG): \$TMP_DIR variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3459 debug "warn" "(CFG): Setting default to: ${_DEFAULT_TMP_DIR}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3460 TMP_DIR=${_DEFAULT_TMP_DIR} 3461 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3462elif [ -z "${TMP_DIR}" ]; then 3463 debug "warn" "(CFG): \$TMP_DIR variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3464 debug "warn" "(CFG): Setting default to: ${_DEFAULT_TMP_DIR}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3465 TMP_DIR=${_DEFAULT_TMP_DIR} 3466 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3467fi 3468 3469# Check directory 3470if [ ! -d "${TMP_DIR}" ]; then 3471 debug "fatal" "(CFG): \$TMP_DIR is not a directory: ${TMP_DIR}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3472 debug "fatal" "(HLP): Change value of \$TMP_DIR in your config" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3473 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3474 exit $EXIT_ABORT 3475elif [ ! -w "${TMP_DIR}" ]; then 3476 debug "fatal" "(CFG): \$TMP_DIR is not writeable" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3477 debug "fatal" "(HLP): Change value of \$TMP_DIR in your config" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3478 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3479 exit $EXIT_ABORT 3480fi 3481debug "trace" "(CFG): Using temporary directory: ${TMP_DIR}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3482 3483 3484 3485 3486############################################################ 3487# Destination Directory and Prefix 3488############################################################ 3489 3490# Check $DUMP_DIR_CHMOD 3491if ! set | grep '^DUMP_DIR_CHMOD=' >/dev/null 2>&1; then 3492 debug "warn" "(CFG): \$DUMP_DIR_CHMOD variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3493 debug "warn" "(CFG): Setting default to: ${_DEFAULT_DUMP_DIR_CHMOD}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3494 DUMP_DIR_CHMOD=${_DEFAULT_DUMP_DIR_CHMOD} 3495 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3496elif [ -z "${DUMP_DIR_CHMOD}" ]; then 3497 debug "warn" "(CFG): \$DUMP_DIR_CHMOD variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3498 debug "warn" "(CFG): Setting default to: ${_DEFAULT_DUMP_DIR_CHMOD}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3499 DUMP_DIR_CHMOD=${_DEFAULT_DUMP_DIR_CHMOD} 3500 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3501elif ! valid_chmod "${DUMP_DIR_CHMOD}" > /dev/null 2>&1; then 3502 debug "warn" "(CFG): Invalid value for \$DUMP_DIR_CHMOD: ${DUMP_DIR_CHMOD}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3503 debug "warn" "(CFG): Setting default to: ${_DEFAULT_DUMP_DIR_CHMOD}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3504 DUMP_DIR_CHMOD="${_DEFAULT_DUMP_DIR_CHMOD}" 3505 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3506fi 3507 3508# Check $DUMP_FILE_CHMOD 3509if ! set | grep '^DUMP_FILE_CHMOD=' >/dev/null 2>&1; then 3510 debug "warn" "(CFG): \$DUMP_FILE_CHMOD variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3511 debug "warn" "(CFG): Setting default to: ${_DEFAULT_DUMP_FILE_CHMOD}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3512 DUMP_FILE_CHMOD=${_DEFAULT_DUMP_DIR_CHMOD} 3513 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3514elif [ -z "${DUMP_FILE_CHMOD}" ]; then 3515 debug "warn" "(CFG): \$DUMP_FILE_CHMOD variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3516 debug "warn" "(CFG): Setting default to: ${_DEFAULT_DUMP_FILE_CHMOD}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3517 DUMP_FILE_CHMOD=${_DEFAULT_DUMP_DIR_CHMOD} 3518 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3519elif ! valid_chmod "${DUMP_FILE_CHMOD}" > /dev/null 2>&1; then 3520 debug "warn" "(CFG): Invalid value for \$DUMP_FILE_CHMOD: ${DUMP_FILE_CHMOD}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3521 debug "warn" "(CFG): Setting default to: ${_DEFAULT_DUMP_FILE_CHMOD}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3522 DUMP_FILE_CHMOD="${_DEFAULT_DUMP_DIR_CHMOD}" 3523 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3524fi 3525 3526# Check $DUMP_DIR 3527if ! set | grep '^DUMP_DIR=' >/dev/null 2>&1; then 3528 debug "warn" "(CFG): \$DUMP_DIR variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3529 debug "warn" "(CFG): Setting default to: ${_DEFAULT_DUMP_DIR}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3530 DUMP_DIR=${_DEFAULT_DUMP_DIR} 3531 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3532elif [ -z "${DUMP_DIR}" ]; then 3533 debug "warn" "(CFG): \$DUMP_DIR variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3534 debug "warn" "(CFG): Setting default to: ${_DEFAULT_DUMP_DIR}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3535 DUMP_DIR=${_DEFAULT_DUMP_DIR} 3536 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3537fi 3538 3539# Resolve symlink? 3540if [ -L "${DUMP_DIR}" ]; then 3541 if _TMP="$(get_file_realpath "${DUMP_DIR}")" >/dev/null 2>&1; then 3542 debug "trace" "(RUN): \$DUMP_DIR is a symlink. Setting target to: ${_TMP}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3543 DUMP_DIR="${_TMP}" 3544 else 3545 debug "fatal" "(RUN): Cannot resolve symlink of: $DUMP_DIR" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3546 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3547 exit $EXIT_ABORT 3548 fi 3549fi 3550 3551if [ ! -d "${DUMP_DIR}" ]; then 3552 debug "warn" "(RUN): Destination dir does not exist: ${DUMP_DIR}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3553 debug_pi "warn" "(RUN): Trying to create... " "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3554 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3555 3556 if ! mkdir -p "${DUMP_DIR}" > /dev/null 2>&1 ; then 3557 debug_i "fatal" "Failed\n" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3558 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3559 exit $EXIT_ABORT 3560 else 3561 debug_i "warn" "Done\n" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3562 debug_pi "warn" "(RUN): Trying to chmod to: ${DUMP_DIR_CHMOD}..." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3563 if ! chmod ${DUMP_DIR_CHMOD} "${DUMP_DIR}" >/dev/null 2>&1; then 3564 debug_i "fatal" "Failed\n" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3565 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3566 exit $EXIT_ABORT 3567 else 3568 debug_i "warn" "Done\n" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3569 fi 3570 fi 3571fi 3572 3573# Check correct permissions of destination dir 3574if ! compare_chmod "$(get_file_chmod "${DUMP_DIR}")" "${DUMP_DIR_CHMOD}" > /dev/null 2>&1 ; then 3575 debug "warn" "(RUN): Destination dir has wrong permissions: $(get_file_chmod "${DUMP_DIR}"), but should ${DUMP_DIR_CHMOD}." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3576 debug_pi "warn" "(RUN): Trying to chmod to ${DUMP_DIR_CHMOD}... " "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3577 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3578 3579 if ! chmod "${DUMP_DIR_CHMOD}" "${DUMP_DIR}" > /dev/null 2>&1 ; then 3580 debug_i "fatal" "Failed\n" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3581 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3582 exit $EXIT_ABORT 3583 else 3584 debug_i "warn" "Done\n" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3585 fi 3586fi 3587# Check if destination dir is writeable 3588if [ ! -w "${DUMP_DIR}" ]; then 3589 debug "fatal" "(RUN): Destination dir ${DUMP_DIR} is not writeable" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3590 debug "fatal" "(HLP): Fix your configured permissions" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3591 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3592 exit $EXIT_ABORT 3593fi 3594 3595# Show information 3596debug "debug" "(CFG): Destination dir: ${DUMP_DIR}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3597 3598 3599# Check $DUMP_FILE_PRE 3600if ! set | grep '^DUMP_FILE_PRE=' >/dev/null 2>&1; then 3601 debug "warn" "(CFG): \$DUMP_FILE_PRE variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3602 debug "warn" "(CFG): Setting default to: ${_DEFAULT_DUMP_FILE_PRE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3603 DUMP_FILE_PRE=${_DEFAULT_DUMP_FILE_PRE} 3604 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3605elif [ -z "${DUMP_FILE_PRE}" ]; then 3606 debug "warn" "(CFG): \$DUMP_FILE_PRE variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3607 debug "warn" "(CFG): Setting default to: ${_DEFAULT_DUMP_FILE_PRE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3608 DUMP_FILE_PRE=${_DEFAULT_DUMP_FILE_PRE} 3609 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3610fi 3611 3612# Show information 3613debug "debug" "(CFG): Using file Prefix: ${DUMP_FILE_PRE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3614 3615 3616 3617############################################################ 3618# MySQL 3619############################################################ 3620 3621# Check Binaries 3622if ! command -v mysql > /dev/null 2>&1 ; then 3623 debug "fatal" "(RUN): 'mysql' not found" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3624 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3625 exit $EXIT_ABORT 3626fi 3627if ! command -v mysqldump > /dev/null 2>&1 ; then 3628 debug "fatal" "(RUN): 'mysqldump' not found" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3629 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3630 exit $EXIT_ABORT 3631fi 3632 3633# Check $MYSQL_CNF_FILE 3634if ! set | grep '^MYSQL_CNF_FILE=' >/dev/null 2>&1; then 3635 debug "fatal" "(CFG): \$MYSQL_CNF_FILE variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3636 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3637 exit $EXIT_ABORT 3638elif [ -z "${MYSQL_CNF_FILE}" ]; then 3639 debug "fatal" "(CFG): \$MYSQL_CNF_FILE variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3640 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3641 exit $EXIT_ABORT 3642fi 3643 3644# Resolve symlink? 3645if [ -L "${MYSQL_CNF_FILE}" ]; then 3646 if _TMP="$(get_file_realpath "${MYSQL_CNF_FILE}")" >/dev/null 2>&1; then 3647 debug "trace" "(RUN): \$MYSQL_CNF_FILE is a symlink. Setting target to: ${_TMP}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3648 MYSQL_CNF_FILE="${_TMP}" 3649 else 3650 debug "fatal" "(RUN): Cannot resolve symlink of: $MYSQL_CNF_FILE" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3651 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3652 exit $EXIT_ABORT 3653 fi 3654fi 3655 3656# Check access and chmod 3657if [ ! -f "${MYSQL_CNF_FILE}" ]; then 3658 debug "fatal" "(RUN): MySQL CNF file not found: ${MYSQL_CNF_FILE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3659 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3660 exit $EXIT_ABORT 3661elif [ ! -r "${MYSQL_CNF_FILE}" ]; then 3662 debug "fatal" "(RUN): MySQL CNF file is not readable: ${MYSQL_CNF_FILE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3663 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3664 exit $EXIT_ABORT 3665elif ! compare_chmod "$(get_file_chmod "${MYSQL_CNF_FILE}")" "${_DEFAULT_MYSQL_CNF_CHMOD}" > /dev/null 2>&1 ; then 3666 debug "fatal" "(RUN): MySQL CNF file has dangerous permissions: $(get_file_chmod "${MYSQL_CNF_FILE}")." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3667 debug "fatal" "(HLP): Fix it to ${_DEFAULT_MYSQL_CNF_CHMOD}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3668 debug "fatal" "(HLP): If you are not alone on the machine, the password inside could have been compromised by now." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3669 debug "fatal" "(HLP): If so, change your database password." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3670 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3671 exit $EXIT_ABORT 3672fi 3673 3674# Validate contents 3675if ! _MSG="$(validate_cnf_file "${MYSQL_CNF_FILE}")"; then 3676 debug "fatal" "(RUN): Invalid cnf file." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3677 debug "fatal" "(HLP): ${_MSG}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3678 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3679 exit $EXIT_ABORT 3680fi 3681 3682 3683 3684# Check MYSQL_SSL_ENABLE 3685if ! set | grep '^MYSQL_SSL_ENABLE=' >/dev/null 2>&1; then 3686 debug "fatal" "(CFG): \$MYSQL_SSL_ENABLE variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3687 debug "fatal" "(HLP): It is not clear whether or not you only allow secure connections." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3688 debug "fatal" "Aborting." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3689 exit $EXIT_ABORT 3690elif [ -z "${MYSQL_SSL_ENABLE}" ]; then 3691 debug "fatal" "(CFG): \$MYSQL_SSL_ENABLE variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3692 debug "fatal" "(HLP): It is not clear whether or not you only allow secure connections." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3693 debug "fatal" "Aborting." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3694 exit $EXIT_ABORT 3695elif [ "${MYSQL_SSL_ENABLE}" = "1" ]; then 3696 if ! set | grep '^MYSQL_SSL_CA_PEM=' >/dev/null 2>&1; then 3697 debug "fatal" "(CFG): \$MYSQL_SSL_CA_PEM variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3698 debug "fatal" "(HLP): It is required for SSL connections" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3699 debug "fatal" "Aborting." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3700 exit $EXIT_ABORT 3701 elif [ -z "${MYSQL_SSL_CA_PEM}" ]; then 3702 debug "fatal" "(CFG): \$MYSQL_SSL_CA_PEM variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3703 debug "fatal" "(HLP): It is required for SSL connections" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3704 debug "fatal" "Aborting." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3705 exit $EXIT_ABORT 3706 elif [ ! -f "${MYSQL_SSL_CA_PEM}" ]; then 3707 debug "fatal" "(RUN): \$MYSQL_SSL_CA_PEM=\"$MYSQL_SSL_CA_PEM\" does not exist" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3708 debug "fatal" "(HLP): It is required for SSL connections" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3709 debug "fatal" "Aborting." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3710 exit $EXIT_ABORT 3711 fi 3712 3713 MYSQL_SSL_ARGS="--ssl-ca=${MYSQL_SSL_CA_PEM}" 3714 3715 # MYSQL_SSL_CLIENT_CERT_PEM 3716 if [ -n "${MYSQL_SSL_CLIENT_CERT_PEM-}" ]; then 3717 if [ ! -f "${MYSQL_SSL_CLIENT_CERT_PEM}" ]; then 3718 debug "fatal" "(RUN): \$MYSQL_SSL_CLIENT_CERT_PEM=\"$MYSQL_SSL_CLIENT_CERT_PEM\" does not exist" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3719 debug "fatal" "(HLP): Comment it out or specify the correct path." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3720 debug "fatal" "Aborting." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3721 exit $EXIT_ABORT 3722 fi 3723 MYSQL_SSL_ARGS="${MYSQL_SSL_ARGS} --ssl-cert=${MYSQL_SSL_CLIENT_CERT_PEM}" 3724 fi 3725 # MYSQL_SSL_CLIENT_KEY_PEM 3726 if [ -n "${MYSQL_SSL_CLIENT_KEY_PEM-}" ]; then 3727 if [ ! -f "${MYSQL_SSL_CLIENT_KEY_PEM}" ]; then 3728 debug "fatal" "(RUN): \$MYSQL_SSL_CLIENT_KEY_PEM=\"$MYSQL_SSL_CLIENT_KEY_PEM\" does not exist" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3729 debug "fatal" "(HLP): Comment it out or specify the correct path." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3730 debug "fatal" "Aborting." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3731 exit $EXIT_ABORT 3732 fi 3733 MYSQL_SSL_ARGS="${MYSQL_SSL_ARGS} --ssl-key=${MYSQL_SSL_CLIENT_KEY_PEM}" 3734 fi 3735 3736 debug "info" "(OPT): MySQL SSL connection enabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3737 debug "debug" "(OPT): MySQL SSL arguments: ${MYSQL_SSL_ARGS}." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3738elif [ "${MYSQL_SSL_ENABLE}" = "0" ]; then 3739 MYSQL_SSL_ENABLE=0 3740 MYSQL_SSL_ARGS="" 3741 debug "info" "(OPT): MySQL SSL connection disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3742else 3743 debug "fatal" "(CFG): Wrong value for \$MYSQL_SSL_ENABLE: $MYSQL_SSL_ENABLE" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3744 debug "fatal" "(HLP): It is not clear whether or not you only allow secure connections." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3745 debug "fatal" "Aborting." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3746 exit $EXIT_ABORT 3747fi 3748 3749 3750 3751 3752############################################################ 3753# MySQL Dump Opts 3754############################################################ 3755 3756# MYSQL_OPTS 3757if ! set | grep '^MYSQL_OPTS=' >/dev/null 2>&1; then 3758 debug "warn" "(CFG): \$MYSQL_OPTS variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3759 debug "warn" "(RUN): Setting default to no custom mysqldump options" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3760 MYSQL_OPTS="" 3761 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3762elif [ -z "${MYSQL_SSL_ENABLE}" ]; then 3763 debug "trace" "(CFG): \$MYSQL_OPTS is empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3764 MYSQL_OPTS="" 3765fi 3766 3767debug "trace" "(CFG): mysqldump custom options: ${MYSQL_OPTS}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3768 3769 3770# MYSQL_OPTS_QUICK_MIN_SIZE 3771if ! set | grep '^MYSQL_OPTS_QUICK_MIN_SIZE=' >/dev/null 2>&1; then 3772 debug "warn" "(CFG): \$MYSQL_OPTS_QUICK_MIN_SIZE variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3773 debug "warn" "(CFG): Setting default to: ${_DEFAULT_MYSQL_OPTS_QUICK_MIN_SIZE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3774 MYSQL_OPTS_QUICK_MIN_SIZE=${_DEFAULT_MYSQL_OPTS_QUICK_MIN_SIZE} 3775 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3776elif [ -z "${MYSQL_OPTS_QUICK_MIN_SIZE}" ]; then 3777 debug "warn" "(CFG): \$MYSQL_OPTS_QUICK_MIN_SIZE is empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3778 debug "warn" "(CFG): Setting default to: ${_DEFAULT_MYSQL_OPTS_QUICK_MIN_SIZE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3779 MYSQL_OPTS_QUICK_MIN_SIZE=${_DEFAULT_MYSQL_OPTS_QUICK_MIN_SIZE} 3780 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3781elif ! isint "${MYSQL_OPTS_QUICK_MIN_SIZE}" >/dev/null 2>&1; then 3782 debug "warn" "(CFG): Wrong integer value for \$MYSQL_OPTS_QUICK_MIN_SIZE: ${MYSQL_OPTS_QUICK_MIN_SIZE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3783 debug "warn" "(CFG): Setting default to: ${_DEFAULT_MYSQL_OPTS_QUICK_MIN_SIZE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3784 MYSQL_OPTS_QUICK_MIN_SIZE=${_DEFAULT_MYSQL_OPTS_QUICK_MIN_SIZE} 3785 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3786fi 3787debug "trace" "(CFG): mysqldump '--quick': Applied to DB's >= ${MYSQL_OPTS_QUICK_MIN_SIZE} MB" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3788debug "trace" "(CFG): mysqldump '--skip-quick': Applied to DB's < ${MYSQL_OPTS_QUICK_MIN_SIZE} MB" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3789 3790 3791############################################################ 3792# Bad MySQL Opts 3793############################################################ 3794for opt in ${MYSQL_OPTS}; do 3795 for evil in ${MDS_MYSQL_EVIL_OPTS}; do 3796 if echo "${opt}" | grep -e "^${evil}" > /dev/null 2>&1; then 3797 debug "fatal" "(CFG): Insecure mysqldump option found in MYSQL_OPTS: '${opt}'" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3798 debug "fatal" "(RUN): Blacklist pattern: '^${evil}'" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3799 debug "fatal" "(HLP): Remove it. This option is handled by the tool itself." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3800 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3801 exit $EXIT_ABORT 3802 fi 3803 done 3804 for bad in ${MDS_MYSQL_BAD_OPTS}; do 3805 if echo "${opt}" | grep -e "^${bad}" > /dev/null 2>&1; then 3806 debug "fatal" "(CFG): Disallowed mysqldump option found in MYSQL_OPTS: '${opt}'" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3807 debug "fatal" "(RUN): Blacklist pattern: '^${bad}'" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3808 debug "fatal" "(HLP): Remove it. This option can be controlled via the configuration file itself." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3809 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3810 exit $EXIT_ABORT 3811 fi 3812 done 3813done 3814 3815 3816 3817 3818 3819############################################################ 3820# Consistency/Transactions 3821############################################################ 3822 3823# CONSISTENT_DUMP_ONLY_INNODB 3824if ! set | grep '^CONSISTENT_DUMP_ONLY_INNODB=' >/dev/null 2>&1; then 3825 debug "warn" "(CFG): \$CONSISTENT_DUMP_ONLY_INNODB variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3826 debug "warn" "(RUN): Setting default to: 1 (using '--single-transaction')" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3827 CONSISTENT_DUMP_ONLY_INNODB="1" 3828 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3829elif [ -z "${CONSISTENT_DUMP_ONLY_INNODB}" ]; then 3830 debug "warn" "(CFG): \$CONSISTENT_DUMP_ONLY_INNODB variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3831 debug "warn" "(RUN): Setting default to: 1 (using '--single-transaction')" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3832 CONSISTENT_DUMP_ONLY_INNODB="1" 3833 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3834elif [ "${CONSISTENT_DUMP_ONLY_INNODB}" = "1" ]; then 3835 debug "trace" "(CFG): InnoDB-only: Dumping consistently across tables (using '--single-transaction')" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3836elif [ "${CONSISTENT_DUMP_ONLY_INNODB}" = "0" ]; then 3837 debug "trace" "(CFG): InnoDB-only: Not dumping consistently across tables (using '--skip-lock-tables') [unsafe]" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3838else 3839 debug "warn" "(CFG): \$CONSISTENT_DUMP_ONLY_INNODB variable has an invalid value: ${CONSISTENT_DUMP_ONLY_INNODB}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3840 debug "warn" "(RUN): Setting default to: 1 (using '--single-transaction')" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3841 CONSISTENT_DUMP_ONLY_INNODB="1" 3842 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3843fi 3844 3845# CONSISTENT_DUMP_NO_INNODB 3846if ! set | grep '^CONSISTENT_DUMP_NO_INNODB=' >/dev/null 2>&1; then 3847 debug "warn" "(CFG): \$CONSISTENT_DUMP_NO_INNODB variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3848 debug "warn" "(RUN): Setting default to: 1 (using '--lock-tables')" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3849 CONSISTENT_DUMP_NO_INNODB="1" 3850 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3851elif [ -z "${CONSISTENT_DUMP_NO_INNODB}" ]; then 3852 debug "warn" "(CFG): \$CONSISTENT_DUMP_NO_INNODB variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3853 debug "warn" "(RUN): Setting default to: 1 (using '--lock-tables')" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3854 CONSISTENT_DUMP_NO_INNODB="1" 3855 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3856elif [ "${CONSISTENT_DUMP_NO_INNODB}" = "1" ]; then 3857 debug "trace" "(CFG): InnoDB-none: Dumping consistently across tables (using '--lock-tables')" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3858elif [ "${CONSISTENT_DUMP_NO_INNODB}" = "0" ]; then 3859 debug "trace" "(CFG): InnoDB-none: Not dumping consistently across tables (using '--skip-lock-tables') [unsafe]" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3860else 3861 debug "warn" "(CFG): \$CONSISTENT_DUMP_NO_INNODB variable has an invalid value: ${CONSISTENT_DUMP_NO_INNODB}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3862 debug "warn" "(RUN): Setting default to: 1 (using '--lock-tables')" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3863 CONSISTENT_DUMP_NO_INNODB="1" 3864 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3865fi 3866 3867# CONSISTENT_DUMP_MIXED_INNODB 3868if ! set | grep '^CONSISTENT_DUMP_MIXED_INNODB=' >/dev/null 2>&1; then 3869 debug "warn" "(CFG): \$CONSISTENT_DUMP_MIXED_INNODB variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3870 debug "warn" "(RUN): Setting default to: 1 (using '--lock-tables')" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3871 CONSISTENT_DUMP_MIXED_INNODB="1" 3872 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3873elif [ -z "${CONSISTENT_DUMP_MIXED_INNODB}" ]; then 3874 debug "warn" "(CFG): \$CONSISTENT_DUMP_MIXED_INNODB variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3875 debug "warn" "(RUN): Setting default to: 1 (using '--lock-tables')" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3876 CONSISTENT_DUMP_MIXED_INNODB="1" 3877 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3878elif [ "${CONSISTENT_DUMP_MIXED_INNODB}" = "1" ]; then 3879 debug "trace" "(CFG): InnoDB-mixed: Dumping consistently across tables (using '--lock-tables')" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3880elif [ "${CONSISTENT_DUMP_MIXED_INNODB}" = "2" ]; then 3881 debug "trace" "(CFG): InnoDB-mixed: Dumping consistently across tables (using '--single-transaction') [unsafe]" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3882elif [ "${CONSISTENT_DUMP_MIXED_INNODB}" = "0" ]; then 3883 debug "trace" "(CFG): InnoDB-mixed: Not dumping consistently across tables (using '--skip-lock-tables') [unsafe]" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3884else 3885 debug "warn" "(CFG): \$CONSISTENT_DUMP_MIXED_INNODB variable has an invalid value: ${CONSISTENT_DUMP_MIXED_INNODB}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3886 debug "warn" "(RUN): Setting default to: 1 (using '--lock-tables')" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3887 CONSISTENT_DUMP_MIXED_INNODB="1" 3888 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3889fi 3890 3891 3892 3893 3894############################################################ 3895# IGNORE/REQUIRE 3896############################################################ 3897 3898# Ignored databases 3899if ! set | grep '^IGNORE=' >/dev/null 2>&1; then 3900 debug "warn" "(CFG): \$IGNORE variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3901 debug "warn" "(HLP): Define \$IGNORE in your config to get rid of this warning" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3902 debug "warn" "(RUN): No database will be ignored" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3903 IGNORE="" 3904 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3905elif [ -z "${IGNORE}" ]; then 3906 debug "trace" "(CFG): \$IGNORE variable is empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3907 debug "trace" "(RUN): No database will be ignored" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3908 IGNORE="" 3909else 3910 debug "trace" "(CFG): Ignored DB's: ${IGNORE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3911fi 3912 3913# Required databases 3914if ! set | grep '^REQUIRE=' >/dev/null 2>&1; then 3915 debug "warn" "(CFG): \$REQUIRE variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3916 debug "warn" "(HLP): Define \$REQUIRE in your config to get rid of this warning" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3917 debug "warn" "(RUN): No database will be required" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3918 REQUIRE="" 3919 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3920elif [ -z "${REQUIRE}" ]; then 3921 debug "trace" "(CFG): \$REQUIRE variable is empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3922 debug "trace" "(RUN): No database will explicitly be required" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3923 REQUIRE="" 3924else 3925 debug "trace" "(CFG): Required DB's: ${REQUIRE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3926fi 3927 3928 3929 3930 3931 3932############################################################ 3933# Compression 3934############################################################ 3935# Check $COMPRESS 3936if ! set | grep '^COMPRESS=' >/dev/null 2>&1; then 3937 debug "warn" "(CFG): \$COMPRESS variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3938 debug "warn" "(OPT): Compression disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3939 COMPRESS=0 3940 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3941elif [ -z "${COMPRESS}" ]; then 3942 debug "warn" "(CFG): \$COMPRESS variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3943 debug "warn" "(OPT): Compression disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3944 COMPRESS=0 3945 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3946elif [ "${COMPRESS}" = "1" ]; then 3947 3948 # COMPRESS_BIN 3949 if ! set | grep '^COMPRESS_BIN=' >/dev/null 2>&1; then 3950 debug "warn" "(CFG): \$COMPRESS_BIN variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3951 debug "warn" "(OPT): Compression disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3952 COMPRESS=0 3953 COMPRESS_BIN="" 3954 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3955 elif [ -z "${COMPRESS_BIN}" ]; then 3956 debug "warn" "(CFG): \$COMPRESS_BIN variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3957 debug "warn" "(OPT): Compression disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3958 COMPRESS=0 3959 COMPRESS_BIN="" 3960 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3961 fi 3962 3963 # If compression is still enabled 3964 if [ "${COMPRESS}" = "1" ]; then 3965 # Does COMPRESS_BIN binary exist? 3966 if ! command -v "${COMPRESS_BIN}" > /dev/null 2>&1 ; then 3967 debug "err" "(CFG): ${COMPRESS_BIN} not found. Fix \$COMPRESS_BIN" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3968 debug "err" "(HLP): Fix \$COMPRESS_BIN" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3969 debug "err" "(OPT): Compression disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3970 COMPRESS=0 3971 MDS_ERROR_COUNT=$((MDS_ERROR_COUNT + 1)) 3972 fi 3973 fi 3974 3975 # If compression is still enabled 3976 if [ "${COMPRESS}" = "1" ]; then 3977 # COMPRESS_ARG 3978 if ! set | grep '^COMPRESS_ARG=' >/dev/null 2>&1; then 3979 debug "warn" "(CFG): \$COMPRESS_ARG variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3980 debug "warn" "(RUN): Using no command line arguments for ${COMPRESS_BIN}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3981 COMPRESS_ARG="" 3982 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3983 # Can be empty 3984 elif [ -z "${COMPRESS_ARG}" ]; then 3985 debug "trace" "(CFG): No compression arguments specified for ${COMPRESS_BIN}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3986 fi 3987 fi 3988 3989 # If compression is still enabled 3990 if [ "${COMPRESS}" = "1" ]; then 3991 # COMPRESS_ARG 3992 if ! set | grep '^COMPRESS_EXT=' >/dev/null 2>&1; then 3993 debug "warn" "(CFG): \$COMPRESS_EXT variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3994 debug "warn" "(RUN): Using 'compressed' as file extension." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3995 COMPRESS_EXT="compressed" 3996 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 3997 elif [ -z "${COMPRESS_EXT}" ]; then 3998 debug "warn" "(CFG): \$COMPRESS_EXT variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 3999 debug "warn" "(RUN): Using 'compressed' as file extension." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4000 COMPRESS_EXT="compressed" 4001 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4002 fi 4003 fi 4004 4005 # If compression is still enabled 4006 if [ "${COMPRESS}" = "1" ]; then 4007 debug "info" "(OPT): Compression enabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4008 debug "debug" "(OPT): Compression arguments: ${COMPRESS_BIN} ${COMPRESS_ARG}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4009 fi 4010 4011elif [ "${COMPRESS}" = "0" ]; then 4012 debug "info" "(OPT): Compression disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4013else 4014 debug "warn" "(CFG): Invalid value for \$COMPRESS: ${COMPRESS}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4015 debug "warn" "(OPT): Compression disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4016 COMPRESS=0 4017 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4018fi 4019 4020 4021 4022############################################################ 4023# Encryption 4024############################################################ 4025if ! set | grep '^ENCRYPT=' >/dev/null 2>&1; then 4026 debug "fatal" "(CFG): \$ENCRYPT variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4027 debug "fatal" "(HLP): It is not clear whether or not you only allow encrypted dumps." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4028 debug "fatal" "Aborting." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4029 exit $EXIT_ABORT 4030elif [ -z "${ENCRYPT}" ]; then 4031 debug "fatal" "(CFG): \$ENCRYPT variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4032 debug "fatal" "(HLP): It is not clear whether or not you only allow encrypted dumps." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4033 debug "fatal" "Aborting." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4034 exit $EXIT_ABORT 4035elif [ "${ENCRYPT}" = "1" ]; then 4036 4037 # OPENSSL_PUBKEY_PEM 4038 if ! set | grep '^OPENSSL_PUBKEY_PEM=' >/dev/null 2>&1; then 4039 debug "fatal" "(CFG): \$OPENSSL_PUBKEY_PEM variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4040 debug "fatal" "Aborting." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4041 exit $EXIT_ABORT 4042 elif [ -z "${OPENSSL_PUBKEY_PEM}" ]; then 4043 debug "fatal" "(CFG): \$OPENSSL_PUBKEY_PEM variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4044 debug "fatal" "Aborting." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4045 exit $EXIT_ABORT 4046 elif [ ! -f "${OPENSSL_PUBKEY_PEM}" ]; then 4047 debug "fatal" "(RUN): OpenSSL pubkey not found in ${OPENSSL_PUBKEY_PEM}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4048 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4049 exit $EXIT_ABORT 4050 elif [ ! -r "${OPENSSL_PUBKEY_PEM}" ]; then 4051 debug "fatal" "(RUN): OpenSSL pubkey not readable" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4052 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4053 exit $EXIT_ABORT 4054 fi 4055 4056 # OpenSSL Algorithm argument 4057 if ! set | grep '^OPENSSL_ALGO_ARG=' >/dev/null 2>&1; then 4058 debug "warn" "(CFG): \$OPENSSL_ALGO_ARG variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4059 debug "warn" "(RUN): Encryption defaults to: ${_DEFAULT_OPENSSL_ALGO_ARG}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4060 OPENSSL_ALGO_ARG="${_DEFAULT_OPENSSL_ALGO_ARG}" 4061 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4062 elif [ -z "${OPENSSL_ALGO_ARG}" ]; then 4063 debug "warn" "(CFG): \$OPENSSL_ALGO_ARG variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4064 debug "warn" "(RUN): Encryption defaults to: ${_DEFAULT_OPENSSL_ALGO_ARG}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4065 OPENSSL_ALGO_ARG="${_DEFAULT_OPENSSL_ALGO_ARG}" 4066 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4067 fi 4068 4069 # Test OpenSSL 4070 if ! command -v openssl > /dev/null 2>&1 ; then 4071 debug "fatal" "(RUN): 'openssl' not found" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4072 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4073 exit $EXIT_ABORT 4074 fi 4075 if ! echo "test" | $(which openssl) smime -encrypt -binary -text -outform DER ${OPENSSL_ALGO_ARG} "${OPENSSL_PUBKEY_PEM}" > /dev/null 2>&1 ; then 4076 debug "fatal" "(RUN): openssl encryption test failed. Validate \$OPENSSL_ALGO_ARG" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4077 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4078 exit $EXIT_ABORT 4079 fi 4080 4081 # ENABLE_SMIME_BUG_WARNING 4082 if ! set | grep '^ENABLE_SMIME_BUG_WARNING=' >/dev/null; then 4083 debug "warn" "(CFG): \$ENABLE_SMIME_BUG_WARNING variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4084 debug "warn" "(CFG): Setting \$ENABLE_SMIME_BUG_WARNING=1" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4085 ENABLE_SMIME_BUG_WARNING=1 4086 elif [ -z "${ENABLE_SMIME_BUG_WARNING}" ]; then 4087 debug "warn" "(CFG): \$ENABLE_SMIME_BUG_WARNING variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4088 debug "warn" "(CFG): Setting \$ENABLE_SMIME_BUG_WARNING=1" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4089 ENABLE_SMIME_BUG_WARNING=1 4090 elif [ "${ENABLE_SMIME_BUG_WARNING}" != "0" ] && [ "${ENABLE_SMIME_BUG_WARNING}" != "1" ]; then 4091 debug "warn" "(CFG): \$ENABLE_SMIME_BUG_WARNING variable has a wrong value: '${ENABLE_SMIME_BUG_WARNING}'" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4092 debug "warn" "(CFG): Setting \$ENABLE_SMIME_BUG_WARNING=1" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4093 ENABLE_SMIME_BUG_WARNING=1 4094 fi 4095 4096 debug "info" "(OPT): Encryption enabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4097 debug "debug" "(OPT): Encryption algorithm: ${OPENSSL_ALGO_ARG}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4098 debug "debug" "(OPT): Encryption pub key: ${OPENSSL_PUBKEY_PEM}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4099 4100elif [ "${ENCRYPT}" = "0" ]; then 4101 debug "info" "(OPT): Encryption disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4102 ENCRYPT="0" 4103else 4104 debug "fatal" "(CFG): Invalid value for \$ENCRYPT: ${ENCRYPT}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4105 debug "fatal" "(HLP): It is not clear whether or not you only allow encrypted dumps." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4106 debug "fatal" "Aborting." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4107 exit $EXIT_ABORT 4108fi 4109 4110 4111 4112############################################################ 4113# Deletion 4114############################################################ 4115 4116if ! set | grep '^DELETE=' >/dev/null 2>&1; then 4117 debug "warn" "(CFG): \$DELETE variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4118 debug "warn" "(OPT): Deletion disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4119 DELETE=0 4120 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4121elif [ -z "${DELETE}" ]; then 4122 debug "warn" "(CFG): \$DELETE variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4123 debug "warn" "(OPT): Deletion disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4124 DELETE=0 4125 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4126elif [ "${DELETE}" = "1" ]; then 4127 4128 # DELETE_METHOD 4129 if ! set | grep '^DELETE_METHOD=' >/dev/null 2>&1; then 4130 debug "warn" "(CFG): \$DELETE_METHOD variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4131 debug "warn" "(OPT): Deletion disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4132 DELETE=0 4133 DELETE_METHOD="" 4134 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4135 elif [ -z "${DELETE_METHOD}" ]; then 4136 debug "warn" "(CFG): \$DELETE_METHOD variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4137 debug "warn" "(OPT): Deletion disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4138 DELETE=0 4139 DELETE_METHOD="" 4140 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4141 elif [ "${DELETE_METHOD}" = "tmpwatch" ] && ! command -v tmpwatch > /dev/null 2>&1 ; then 4142 debug "err" "(RUN): 'tmpwatch' not found" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4143 debug "err" "(OPT): Deletion disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4144 DELETE=0 4145 DELETE_METHOD="" 4146 MDS_ERROR_COUNT=$((MDS_ERROR_COUNT + 1)) 4147 elif [ "${DELETE_METHOD}" = "tmpreaper" ] && ! command -v tmpreaper > /dev/null 2>&1 ; then 4148 debug "err" "(RUN): 'tmpreaper' not found" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4149 debug "err" "(OPT): Deletion disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4150 DELETE=0 4151 DELETE_METHOD="" 4152 MDS_ERROR_COUNT=$((MDS_ERROR_COUNT + 1)) 4153 elif [ "${DELETE_METHOD}" != "tmpwatch" ] && [ "${DELETE_METHOD}" != 'tmpreaper' ]; then 4154 debug "err" "(CFG): \$DELETE_METHOD must be either 'tmpwatch' or 'tmpreaper' in ${CONFIG_FILE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4155 debug "err" "(OPT): Deletion disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4156 DELETE=0 4157 DELETE_METHOD="" 4158 MDS_ERROR_COUNT=$((MDS_ERROR_COUNT + 1)) 4159 else 4160 4161 # DELETE_IF_OLDER 4162 if ! set | grep '^DELETE_IF_OLDER=' >/dev/null 2>&1; then 4163 debug "warn" "(CFG): \$DELETE_IF_OLDER variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4164 debug "warn" "(OPT): Deletion disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4165 DELETE=0 4166 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4167 elif [ -z "${DELETE_IF_OLDER}" ]; then 4168 debug "warn" "(CFG): \$DELETE_IF_OLDER variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4169 debug "warn" "(OPT): Deletion disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4170 DELETE=0 4171 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4172 elif ! valid_tmpwatch "${DELETE_IF_OLDER}" > /dev/null 2>&1 ; then 4173 debug "err" "(CFG): \$DELETE_IF_OLDER does not have a valid ${DELETE_METHOD} value: ${DELETE_IF_OLDER}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4174 debug "err" "(HLP): See: man ${DELETE_METHOD}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4175 debug "err" "(OPT): Deletion disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4176 DELETE=0 4177 MDS_ERROR_COUNT=$((MDS_ERROR_COUNT + 1)) 4178 fi 4179 fi 4180 4181 # If deletion is still enabled 4182 if [ "${DELETE}" = "1" ]; then 4183 4184 debug "info" "(OPT): Deletion enabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4185 debug "debug" "(OPT): Deleting files older than $(get_tmpwatch_value "${DELETE_IF_OLDER}") $(get_tmpwatch_unit_name "${DELETE_IF_OLDER}"). Using: ${DELETE_METHOD}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4186 4187 # DELETE_FORCE 4188 if ! set | grep '^DELETE_FORCE=' >/dev/null 2>&1; then 4189 debug "warn" "(CFG): \$DELETE_FORCE variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4190 debug "warn" "(RUN): Setting \$DELETE_FORCE = 0" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4191 DELETE_FORCE=0 4192 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4193 elif [ -z "${DELETE_FORCE}" ]; then 4194 debug "warn" "(CFG): \$DELETE_FORCE variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4195 debug "warn" "(RUN): Setting \$DELETE_FORCE = 0" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4196 DELETE_FORCE=0 4197 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4198 elif [ "${DELETE_FORCE}" = "1" ]; then 4199 debug "trace" "(CFG): ${DELETE_METHOD}: Using '--force' option (deleting read-only files)" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4200 elif [ "${DELETE_FORCE}" = "0" ]; then 4201 debug "trace" "(CFG): ${DELETE_METHOD}: Not forcing (--force) deletion for read-only files" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4202 else 4203 debug "err" "(CFG): Invalid value for \$DELETE_FORCE: ${DELETE_FORCE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4204 debug "err" "(RUN): Setting \$DELETE_FORCE = 0" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4205 DELETE_FORCE=0 4206 MDS_ERROR_COUNT=$((MDS_ERROR_COUNT + 1)) 4207 fi 4208 fi 4209 4210elif [ "${DELETE}" = "0" ]; then 4211 debug "info" "(OPT): Deletion disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4212else 4213 debug "err" "(CFG): Invalid value for \$DELETE: ${DELETE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4214 debug "err" "(OPT): Deletion disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4215 DELETE=0 4216 MDS_ERROR_COUNT=$((MDS_ERROR_COUNT + 1)) 4217fi 4218 4219 4220 4221 4222 4223############################################################ 4224# Nagios 4225############################################################ 4226# NAGIOS_LOG 4227if ! set | grep '^NAGIOS_LOG=' >/dev/null 2>&1; then 4228 debug "warn" "(CFG): \$NAGIOS_LOG variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4229 debug "warn" "(OPT): Nagios log disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4230 NAGIOS_LOG=0 4231 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4232elif [ -z "${NAGIOS_LOG}" ]; then 4233 debug "warn" "(CFG): \$NAGIOS_LOG variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4234 debug "warn" "(OPT): Nagios log disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4235 NAGIOS_LOG=0 4236 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4237elif [ "${NAGIOS_LOG}" = "1" ]; then 4238 4239 # NAGIOS_LOG_CHMOD 4240 if ! set | grep '^NAGIOS_LOG_CHMOD=' >/dev/null 2>&1; then 4241 debug "warn" "(CFG): \$NAGIOS_LOG_CHMOD variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4242 debug "warn" "(RUN): Setting default to ${_DEFAULT_NAGIOS_LOG_CHMOD}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4243 NAGIOS_LOG_CHMOD="${_DEFAULT_NAGIOS_LOG_CHMOD}" 4244 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4245 elif [ -z "${NAGIOS_LOG_CHMOD}" ]; then 4246 debug "warn" "(CFG): \$NAGIOS_LOG_CHMOD variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4247 debug "warn" "(RUN): Setting default to ${_DEFAULT_NAGIOS_LOG_CHMOD}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4248 NAGIOS_LOG_CHMOD="${_DEFAULT_NAGIOS_LOG_CHMOD}" 4249 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4250 elif ! valid_chmod "${NAGIOS_LOG_CHMOD}" > /dev/null 2>&1; then 4251 debug "err" "(CFG): Invalid chmod value for \$NAGIOS_LOG_CHMOD: ${NAGIOS_LOG_CHMOD}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4252 debug "err" "(RUN): Setting default to ${_DEFAULT_NAGIOS_LOG_CHMOD}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4253 NAGIOS_LOG_CHMOD="${_DEFAULT_NAGIOS_LOG_CHMOD}" 4254 MDS_ERROR_COUNT=$((MDS_ERROR_COUNT + 1)) 4255 fi 4256 4257 # NAGIOS_LOG_FILE 4258 if ! set | grep '^NAGIOS_LOG_FILE=' >/dev/null 2>&1; then 4259 debug "warn" "(CFG): \$NAGIOS_LOG_FILE variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4260 debug "warn" "(OPT): Nagios log disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4261 NAGIOS_LOG=0 4262 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4263 elif [ -z "${NAGIOS_LOG_FILE}" ]; then 4264 debug "warn" "(CFG): \$NAGIOS_LOG_FILE variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4265 debug "warn" "(OPT): Nagios log disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4266 NAGIOS_LOG=0 4267 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4268 elif [ ! -f "${NAGIOS_LOG_FILE}" ]; then 4269 debug "warn" "(RUN): ${NAGIOS_LOG_FILE} not found" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4270 debug_pi "warn" "(RUN): Trying to create..." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4271 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4272 4273 if ! touch "${NAGIOS_LOG_FILE}" > /dev/null 2>&1 ; then 4274 debug_i "err" "Failed\n" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4275 debug "err" "(RUN): Failed to create file ${NAGIOS_LOG_FILE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4276 debug "err" "(OPT): Nagios log disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4277 NAGIOS_LOG=0 4278 MDS_ERROR_COUNT=$((MDS_ERROR_COUNT + 1)) 4279 else 4280 debug_i "warn" "OK\n" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4281 debug "warn" "(RUN): Created file ${NAGIOS_LOG_FILE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4282 debug_pi "warn" "(RUN): Trying to chmod to ${NAGIOS_LOG_CHMOD}..." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4283 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4284 4285 if ! chmod ${NAGIOS_LOG_CHMOD} "${NAGIOS_LOG_FILE}" > /dev/null 2>&1 ; then 4286 debug_i "err" "Failed\n" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4287 debug "err" "(RUN): Failed to chmod ${NAGIOS_LOG_CHMOD} ${NAGIOS_LOG_FILE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4288 debug "err" "(OPT): Nagios log disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4289 NAGIOS_LOG=0 4290 MDS_ERROR_COUNT=$((MDS_ERROR_COUNT + 1)) 4291 else 4292 debug_i "warn" "OK\n" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4293 fi 4294 fi 4295 # Check if it has wrong permissions 4296 elif ! compare_chmod "$(get_file_chmod "${NAGIOS_LOG_FILE}")" "${NAGIOS_LOG_CHMOD}" > /dev/null 2>&1 ; then 4297 debug "warn" "(RUN): Nagios log file has wrong permissions: $(get_file_chmod "${NAGIOS_LOG_FILE}"), but should be: ${NAGIOS_LOG_CHMOD} " "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4298 debug_pi "warn" "(RUN): Trying to chmod to ${NAGIOS_LOG_CHMOD}... " "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4299 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4300 4301 if ! chmod "${NAGIOS_LOG_CHMOD}" "${NAGIOS_LOG_FILE}" > /dev/null 2>&1 ; then 4302 debug_i "err" "Failed\n" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4303 debug "err" "(RUN): Failed to chmod ${NAGIOS_LOG_CHMOD} ${NAGIOS_LOG_FILE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4304 debug "err" "(OPT): Nagios plugin log disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4305 NAGIOS_LOG=0 4306 MDS_ERROR_COUNT=$((MDS_ERROR_COUNT + 1)) 4307 else 4308 debug_i "warn" "OK\n" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4309 fi 4310 fi 4311 4312 # Still enabled? 4313 if [ "${NAGIOS_LOG}" = "1" ]; then 4314 if [ ! -r "${NAGIOS_LOG_FILE}" ]; then 4315 debug "warn" "(RUN): ${NAGIOS_LOG_FILE} not readable" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4316 debug "warn" "(HLP): FIX \NAGIOS_LOG_CHMOD value in config" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4317 debug "warn" "(OPT): Nagios log disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4318 NAGIOS_LOG=0 4319 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4320 elif [ ! -w "${NAGIOS_LOG_FILE}" ]; then 4321 debug "warn" "(RUN): ${NAGIOS_LOG_FILE} not writeable" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4322 debug "warn" "(HLP): FIX \NAGIOS_LOG_CHMOD value in config" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4323 debug "warn" "(OPT): Nagios log disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4324 NAGIOS_LOG=0 4325 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4326 else 4327 debug "info" "(OPT): Nagios log enabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4328 debug "debug" "(OPT): Nagios log file: ${NAGIOS_LOG_FILE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4329 fi 4330 fi 4331 4332elif [ "${NAGIOS_LOG}" = "0" ]; then 4333 debug "info" "(OPT): Nagios log disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4334else 4335 debug "err" "(CFG): Invalid value for \$NAGIOS_LOG: ${NAGIOS_LOG}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4336 debug "err" "(OPT): Nagios log disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4337 DELETE=0 4338 MDS_ERROR_COUNT=$((MDS_ERROR_COUNT + 1)) 4339fi 4340 4341 4342 4343 4344############################################################ 4345# Info file 4346############################################################ 4347 4348if ! set | grep '^DUMP_FILE_INFO=' >/dev/null 2>&1; then 4349 debug "warn" "(CFG): \$DUMP_FILE_INFO variable is not defined" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4350 debug "warn" "(OPT): Info files disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4351 DUMP_FILE_INFO=0 4352 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4353elif [ -z "${DUMP_FILE_INFO}" ]; then 4354 debug "warn" "(CFG): \$DUMP_FILE_INFO variable should not be empty" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4355 debug "warn" "(OPT): Info files disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4356 DUMP_FILE_INFO=0 4357 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4358elif [ "${DUMP_FILE_INFO}" = "1" ]; then 4359 debug "info" "(OPT): Info files enabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4360elif [ "${DUMP_FILE_INFO}" = "0" ]; then 4361 debug "info" "(OPT): Info files disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4362else 4363 debug "warn" "(CFG): Invalid value for \$DUMP_FILE_INFO: ${DUMP_FILE_INFO}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4364 debug "warn" "(OPT): Info files disabled" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4365 DUMP_FILE_INFO=0 4366 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4367fi 4368 4369 4370 4371 4372 4373 4374############################################################ 4375# Connection 4376############################################################ 4377 4378 4379# Testing MySQL Connection 4380if ! _CONN_ERR="$( mysql_test_connection "${MYSQL_CNF_FILE}" "${MYSQL_SSL_ARGS}" )"; then 4381 debug "fatal" "(RUN): Cannot connect to mysql database." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4382 debug "fatal" "(RUN): Via: $(which mysql) --defaults-file=${MYSQL_CNF_FILE} ${MYSQL_SSL_ARGS}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4383 debug "fatal" "(RUN): SQL: ${_CONN_ERR}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4384 debug "fatal" "(HLP): Fix credentials in: ${MYSQL_CNF_FILE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4385 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4386 exit $EXIT_ABORT 4387else 4388 debug "trace" "(RUN): MySQL connection test successful." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4389fi 4390 4391 4392# Getting MySQL Server Status 4393if ! MYSQL_SERVER_STATUS="$( get_mysql_server_status "${MYSQL_CNF_FILE}" "${MYSQL_SSL_ARGS}" )"; then 4394 debug "fatal" "(SRV): Cannot retrieve MySQL server status" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4395 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4396 exit $EXIT_ABORT 4397fi 4398 4399 4400# MySQL TCP/IP or Socket connection 4401debug "debug" "(SRV): MySQL server connection: $( get_mysql_connection_type_info "${MYSQL_SERVER_STATUS}" )" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4402 4403 4404# Testing MySQL for SSL connection 4405MYSQL_SSL_STATUS="$( get_mysql_connection_ssl_info "${MYSQL_SERVER_STATUS}" )" 4406if [ "${MYSQL_SSL_STATUS}" = "Not in use" ]; then 4407 if [ "${MYSQL_SSL_ENABLE}" = "1" ]; then 4408 debug "fatal" "(SRV): MySQL server connection: Not using SSL, but demanded." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4409 debug "fatal" "(HLP): We have already made some plain-text connections" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4410 debug "fatal" "(HLP): It is advised to change your password immediately" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4411 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4412 exit $EXIT_ABORT 4413 else 4414 debug "debug" "(SRV): MySQL server connection: Not using SSL (plain)." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4415 fi 4416else 4417 debug "debug" "(SRV): MySQL server connection: Using SSL (${MYSQL_SSL_STATUS})" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4418fi 4419 4420# Testing MySQL for Master or Slave 4421if ! MYSQL_SERVER_TYPE="$(get_mysql_server_replication_type "${MYSQL_CNF_FILE}" "${MYSQL_SSL_ARGS}")"; then 4422 debug "fatal" "(RUN): Connection error" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4423 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4424 exit $EXIT_ABORT 4425else 4426 debug "debug" "(SRV): MySQL server rep type: ${MYSQL_SERVER_TYPE}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4427fi 4428 4429 4430# Get MySQL Name and Version 4431MYSQL_SERVER="$( get_mysql_server_name "${MYSQL_SERVER_STATUS}" )" 4432MYSQL_VERSION="$( get_mysql_server_version "${MYSQL_SERVER_STATUS}" )" 4433 4434# Get MySQL Server Hostname and Port 4435MYSQL_HOST="$( get_mysql_server_hostname "${MYSQL_CNF_FILE}" "${MYSQL_SSL_ARGS}" )" 4436MYSQL_PORT="$( get_mysql_server_port "${MYSQL_CNF_FILE}" "${MYSQL_SSL_ARGS}" )" 4437 4438debug "debug" "(SRV): MySQL server version: $( [ "${MYSQL_SERVER}" != "" ] && echo "${MYSQL_SERVER} " )${MYSQL_VERSION}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4439debug "debug" "(SRV): MySQL server hostname: ${MYSQL_HOST}:${MYSQL_PORT}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451############################################################ 4452# Test mode 4453############################################################ 4454if [ "${_ARG_TEST}" = "1" ]; then 4455 debug "info" "(ARG): Exiting program from test mode (--test)." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4456 exit $EXIT_OK 4457fi 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473#################################################################################################### 4474#################################################################################################### 4475## 4476## M A I N E N T R Y P O I N T ( R U N ) 4477## 4478#################################################################################################### 4479#################################################################################################### 4480 4481 4482################################################################################ 4483# 4484# VARIABLES 4485# 4486################################################################################ 4487 4488# 4489# Binaries 4490# 4491BIN_TMPWATCH="$(which "${DELETE_METHOD}" 2>/dev/null)" # This can be tmpwatch or tmpreaper 4492 4493# 4494# Database counters 4495# 4496DB_CNT_TOTAL=0 # Total numbers of databases 4497DB_CNT_IGNORED=0 # Number of ignored databases (empty or via ignore list) 4498DB_CNT_DUMPED=0 # Number of successfully dumped databases 4499DB_CNT_FAILED=0 # Number of unseccessfull dumped fatabases (failed) 4500DB_CNT_REQ_FAILED=0 # Number of required databases not dumped 4501 4502# 4503# Database lists 4504# 4505DB_LIST_ALL="" # Newline separated list of all databases 4506DB_LIST_DUMPED="" # Comma separated list of all dumped databases 4507DB_LIST_IGNORED="" # Comma separated list of all ignored databases 4508DB_LIST_FAILED="" # Comma separated list of all failed databases 4509DB_LIST_REQ_FAILED="" # Comma separated list of required databases not dumped 4510 4511# 4512# Total size of all dumped databases 4513# 4514TOTAL_SIZE_B=0 4515TOTAL_SIZE_MB=0 4516 4517# 4518# Overall Timing 4519# 4520TIME_TOTAL_START=0 4521TIME_TOTAL_DURATION=0 4522 4523 4524 4525# 4526# Nagios Log: Aggregated exit code (0:OK, 1:Warn, 2:ERR, 3:UNKNOWN) 4527# 4528NAGIOS_EXIT_CODE=0 4529 4530 4531 4532# 4533# TODO: Make all vars within 'if' local and small _tmp_bla 4534# 4535# 4536 4537 4538################################################################################ 4539# 4540# PRE-PROCESSING 4541# 4542################################################################################ 4543 4544 4545 4546############################################################ 4547# Create tmp files and folders 4548############################################################ 4549 4550# New temporary directory 4551if MY_TMP_DIR="$(create_tmp_dir "${TMP_DIR}/${INFO_NAME}.XXXXXXXXXX" "0700")"; then 4552 debug "trace" "(RUN): Creating tmp dir: ${MY_TMP_DIR}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4553else 4554 debug "fatal" "(RUN): Cannot create tmp dir: ${MY_TMP_DIR}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4555 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4556 exit $EXIT_ABORT 4557fi 4558 4559# Temp file 'tmpwatch/tmpreaper' 4560if [ "${DELETE}" = "1" ]; then 4561 if MY_TMP_FILE_DEL="$(create_tmp_file "${MY_TMP_DIR}/.XXXXXXXXXXXXXXX" "0600")"; then 4562 debug "trace" "(RUN): Creating tmp file: ${MY_TMP_FILE_DEL}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4563 else 4564 debug "fatal" "(RUN): Cannot create tmp file: ${MY_TMP_FILE_DEL}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4565 debug "fatal" "Aborting" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4566 exit $EXIT_ABORT 4567 fi 4568fi 4569 4570 4571############################################################ 4572# Get all databases 4573############################################################ 4574 4575debug_pi "debug" "(SQL): Retrieving list of databases... " "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4576 4577# Get all databases 4578DB_LIST_ALL="$( get_mysql_databases "${MYSQL_CNF_FILE}" "${MYSQL_SSL_ARGS}" )" 4579DB_CNT_TOTAL="$( str_count_lines "${DB_LIST_ALL}" )" 4580 4581debug_i "debug" "${DB_CNT_TOTAL}\n" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4582 4583 4584 4585 4586 4587################################################################################ 4588# 4589# DUMP DATABASES 4590# 4591################################################################################ 4592 4593 4594i=0 # Lopp counter 4595TIME_TOTAL_START="$( get_time )" 4596for db in ${DB_LIST_ALL}; do 4597 4598 4599 ########################################################## 4600 # VARIABLES 4601 4602 # Increment Loop counter 4603 i=$((i + 1)) 4604 4605 # Show progress 4606 # At which database are we right now? 4607 # Left-space-padded " 1/10" counter 4608 _cnt="$(printf "%$(str_len "${DB_CNT_TOTAL}")d/%d" "${i}" "${DB_CNT_TOTAL}")" 4609 4610 # File extension for dump file (.sql, .sql.gz, .sql.gz.enc or .sql.enc) 4611 ext="$( build_file_extension "${ENCRYPT}" "${COMPRESS}" "${COMPRESS_EXT}" )" 4612 4613 # Skip database vars 4614 skip_empty=0 4615 skip_ignored=0 4616 4617 4618 4619 4620 4621 ########################################################## 4622 # IGNORE CHECKS 4623 4624 4625 # Empty databases 4626 if mysql_database_is_empty "${MYSQL_CNF_FILE}" "${MYSQL_SSL_ARGS}" "${db}"; then 4627 skip_empty=1 4628 fi 4629 4630 # Ignored database 4631 if _ignore_pattern="$( database_is_ignored "${IGNORE}" "${db}" )"; then 4632 skip_ignored=1 4633 debug "trace" "(CFG): ${_cnt} Ignoring DB: \"${db}\" by \$IGNORE pattern: \"${_ignore_pattern}\"" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4634 4635 # Only if ignored database is not required, we can ignore it. 4636 if database_is_required "${REQUIRE}" "${db}"; then 4637 skip_ignored=0 4638 debug "trace" "(CFG): ${_cnt} Required DB: \"${db}\" un-ignored by \$REQUIRE settings" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4639 fi 4640 fi 4641 4642 4643 # 4644 # Main case 1 (skipping) 4645 # 4646 if [ "${skip_empty}" = "1" ] || [ "${skip_ignored}" = "1" ]; then 4647 4648 # Case 1/3: Empty AND Ignored 4649 if [ "${skip_empty}" = "1" ] && [ "${skip_ignored}" = "1" ]; then 4650 debug "info" "(SQL): ${_cnt} Skipping: ${db} (DB is empty and ignored)" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4651 # Case 2/3: Empty 4652 elif [ "${skip_empty}" = "1" ]; then 4653 debug "info" "(SQL): ${_cnt} Skipping: ${db} (DB is empty)" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4654 # Case 3/3:Ignored 4655 else 4656 debug "info" "(SQL): ${_cnt} Skipping: ${db} (DB is ignored)" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4657 fi 4658 4659 DB_CNT_IGNORED=$((DB_CNT_IGNORED + 1)) 4660 DB_LIST_IGNORED="$( str_join "${DB_LIST_IGNORED}" "," "${db}" )" 4661 4662 # 4663 # Main case 2 (file exists on disk) 4664 # 4665 elif [ -f "${DUMP_DIR}/${DUMP_FILE_PRE}${db}${ext}" ]; then 4666 4667 # Increment counters 4668 DB_CNT_FAILED=$((DB_CNT_FAILED + 1)) 4669 MDS_FAIL_COUNT=$((MDS_FAIL_COUNT + 1)) 4670 4671 # Add failed db to nagios log 4672 DB_LIST_FAILED="$( str_join "${DB_LIST_FAILED}" "," "${db}" )" 4673 4674 debug "fatal" "(RUN): ${_cnt} Failed: ${db} cannot be written to disk (file exists: ${DUMP_DIR}/${DUMP_FILE_PRE}${db}${ext})" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4675 NAGIOS_EXIT_CODE="$(merge_exit_codes "${NAGIOS_EXIT_CODE}" 2)" 4676 4677 # 4678 # Main case 3 (dumping) 4679 # 4680 else 4681 4682 ########################################################## 4683 # VARIABLES 4684 4685 # Database size 4686 DB_SIZE_B="$( get_mysql_database_size "${MYSQL_CNF_FILE}" "${MYSQL_SSL_ARGS}" "${db}" )" 4687 DB_SIZE_MB="$( div "${DB_SIZE_B}" "1048576" )" 4688 DB_SIZE_MB="$( round "${DB_SIZE_MB}" "2" )" 4689 4690 # Total Database size (aggregated db size) 4691 TOTAL_SIZE_B=$( sum "${TOTAL_SIZE_B}" "${DB_SIZE_B}" ) 4692 4693 # Number of tables 4694 TBL_CNT_TOTAL="$( count_total_tables "${MYSQL_CNF_FILE}" "${MYSQL_SSL_ARGS}" "${db}" )" 4695 TBL_CNT_INNODB="$( count_innodb_tables "${MYSQL_CNF_FILE}" "${MYSQL_SSL_ARGS}" "${db}" )" 4696 TBL_CNT_OTHERS="$( count_non_innodb_tables "${MYSQL_CNF_FILE}" "${MYSQL_SSL_ARGS}" "${db}" )" 4697 4698 debug "trace" "(RUN): ${_cnt} Number of total tables: ${TBL_CNT_TOTAL}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4699 debug "trace" "(RUN): ${_cnt} Number of InnoDB tables: ${TBL_CNT_INNODB}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4700 debug "trace" "(RUN): ${_cnt} Number of non-InnoDB tables: ${TBL_CNT_OTHERS}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4701 4702 4703 ########################################################## 4704 # MYSQLDUMP OPTIONS 4705 4706 # 4707 # CONSISTENCY OPTIONS (By Table Engines) 4708 # 4709 # information_schema and performance schema are special tables, which do not allow locking 4710 if [ "${db}" != "information_schema" ] && [ "${db}" != "performance_schema" ]; then 4711 MYSQL_LOCK_OPTS="$( get_consistency_opts "${CONSISTENT_DUMP_ONLY_INNODB}" "${CONSISTENT_DUMP_MIXED_INNODB}" "${CONSISTENT_DUMP_NO_INNODB}" "${TBL_CNT_INNODB}" "${TBL_CNT_OTHERS}" )" 4712 debug "trace" "(RUN): ${_cnt} Applying consistency setting: ${MYSQL_LOCK_OPTS}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4713 else 4714 MYSQL_LOCK_OPTS="--skip-lock-tables" 4715 debug "trace" "(RUN): ${_cnt} \"${db}\" is special and needs '--skip-lock-tables'" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4716 fi 4717 4718 # 4719 # SPECIAL OPTIONS (By Virtual Databases) 4720 # 4721 MYSQL_SPECIAL_OPTS="" 4722 4723 # Performance schema does not allow to dump events 4724 # mysqldump: mysqldump Couldn't execute 'show events' Access denied for user 'root'@'localhost' to database 'performance_schema' (1044) 4725 if [ "${db}" = "performance_schema" ]; then 4726 MYSQL_SPECIAL_OPTS="--skip-events" 4727 debug "trace" "(RUN): ${_cnt} \"${db}\" cannot be dumped with --events. Adding --skip-events" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4728 fi 4729 4730 # 4731 # QUICK OPTION (--quick/--skip-quick dependent on size) 4732 # 4733 MYSQL_QUICK_OPT="$(echo "${DB_SIZE_MB} ${MYSQL_OPTS_QUICK_MIN_SIZE}" | awk '{print ($1 >= $2) ? "--quick" : "--skip-quick" }')" 4734 4735 # 4736 # FINAL OPTIONS (Build final MySQLDump arguments) 4737 # 4738 MYSQL_ARGUMENTS="--defaults-file=${MYSQL_CNF_FILE} ${MYSQL_SSL_ARGS}" 4739 MYSQLDUMP_ARGUMENTS="${MYSQL_OPTS} ${MYSQL_LOCK_OPTS} ${MYSQL_SPECIAL_OPTS} ${MYSQL_QUICK_OPT}" 4740 4741 4742 4743 ########################################################## 4744 # SMIME WARNING 4745 # https://github.com/cytopia/mysqldump-secure/issues/21 4746 4747 # Warn about SMIME bug for files > 1200MB 4748 SMIME_CRITICAL_SIZE_MB="1200" 4749 if [ "${ENCRYPT}" = "1" ] && [ "${ENABLE_SMIME_BUG_WARNING}" = "1" ] && [ "$( printf "%.0f\n" "${DB_SIZE_MB}" )" -gt "${SMIME_CRITICAL_SIZE_MB}" ]; then 4750 debug "warn" "(SQL): ${_cnt} Warning: Encryption is enabled and database size is > ${SMIME_CRITICAL_SIZE_MB} MB" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4751 debug "warn" "(SQL): ${_cnt} Warning: Verify that your backup can be decrypted." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4752 debug "warn" "(SQL): ${_cnt} Warning: This warning can be disabled via 'ENABLE_SMIME_BUG_WARNING=0'" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4753 debug "warn" "(SQL): ${_cnt} Warning: Read here: https://github.com/cytopia/mysqldump-secure/issues/21" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4754 fi 4755 4756 4757 ########################################################## 4758 # MAKE THE BACKUPS 4759 4760 debug_pi "info" "(SQL): ${_cnt} Dumping: ${db} (${DB_SIZE_MB} MB) " "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4761 4762 4763 # 4764 # Stop time (start) 4765 # 4766 starttime="$( get_time )" 4767 4768 # 4769 # Case 1/4 Plain 4770 # 4771 if [ "${COMPRESS}" = "0" ] && [ "${ENCRYPT}" = "0" ]; then 4772 4773 debug_i "debug" "$( [ "${MYSQL_LOCK_OPTS}" != "" ] && echo "(${MYSQL_LOCK_OPTS}) ")$( [ "${MYSQL_SPECIAL_OPTS}" != "" ] && echo "(${MYSQL_SPECIAL_OPTS}) ")(${MYSQL_QUICK_OPT}) " "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4774 4775 # Run Compressed & Encrypted 4776 error_statuses="$(run_mysqldump "0" "${MYSQL_ARGUMENTS} ${MYSQLDUMP_ARGUMENTS}" "${db}" \ 4777 "${DUMP_DIR}/${DUMP_FILE_PRE}${db}${ext}" "${DUMP_FILE_CHMOD}" \ 4778 "${COMPRESS_BIN}" "${COMPRESS_ARG}" \ 4779 "${OPENSSL_ALGO_ARG}" "${OPENSSL_PUBKEY_PEM}" \ 4780 "${MY_TMP_DIR}" 4781 )" 4782 # 4783 # Case 2/4 Compressed 4784 # 4785 elif [ "${COMPRESS}" = "1" ] && [ "${ENCRYPT}" = "0" ]; then 4786 4787 debug_i "debug" "(compressed) $( [ "${MYSQL_LOCK_OPTS}" != "" ] && echo "(${MYSQL_LOCK_OPTS}) ")$( [ "${MYSQL_SPECIAL_OPTS}" != "" ] && echo "(${MYSQL_SPECIAL_OPTS}) ")(${MYSQL_QUICK_OPT}) " "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4788 4789 # Run Compressed & Encrypted 4790 error_statuses="$(run_mysqldump "1" "${MYSQL_ARGUMENTS} ${MYSQLDUMP_ARGUMENTS}" "${db}" \ 4791 "${DUMP_DIR}/${DUMP_FILE_PRE}${db}${ext}" "${DUMP_FILE_CHMOD}" \ 4792 "${COMPRESS_BIN}" "${COMPRESS_ARG}" \ 4793 "${OPENSSL_ALGO_ARG}" "${OPENSSL_PUBKEY_PEM}" \ 4794 "${MY_TMP_DIR}" 4795 )" 4796 # 4797 # Case 3/4 Encrypted 4798 # 4799 elif [ "${COMPRESS}" = "0" ] && [ "${ENCRYPT}" = "1" ]; then 4800 4801 debug_i "debug" "(encrypted) $( [ "${MYSQL_LOCK_OPTS}" != "" ] && echo "(${MYSQL_LOCK_OPTS}) ")$( [ "${MYSQL_SPECIAL_OPTS}" != "" ] && echo "(${MYSQL_SPECIAL_OPTS}) ")(${MYSQL_QUICK_OPT}) " "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4802 4803 # Run Compressed & Encrypted 4804 error_statuses="$(run_mysqldump "2" "${MYSQL_ARGUMENTS} ${MYSQLDUMP_ARGUMENTS}" "${db}" \ 4805 "${DUMP_DIR}/${DUMP_FILE_PRE}${db}${ext}" "${DUMP_FILE_CHMOD}" \ 4806 "${COMPRESS_BIN}" "${COMPRESS_ARG}" \ 4807 "${OPENSSL_ALGO_ARG}" "${OPENSSL_PUBKEY_PEM}" \ 4808 "${MY_TMP_DIR}" 4809 )" 4810 # 4811 # Case 4/4 Compressed && Encrypted 4812 # 4813 elif [ "${COMPRESS}" = "1" ] && [ "${ENCRYPT}" = "1" ]; then 4814 4815 debug_i "debug" "(compressed) (encrypted) $( [ "${MYSQL_LOCK_OPTS}" != "" ] && echo "(${MYSQL_LOCK_OPTS}) " )$( [ "${MYSQL_SPECIAL_OPTS}" != "" ] && echo "(${MYSQL_SPECIAL_OPTS}}) ")(${MYSQL_QUICK_OPT}) " "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4816 4817 # Run Compressed & Encrypted 4818 error_statuses="$(run_mysqldump "3" "${MYSQL_ARGUMENTS} ${MYSQLDUMP_ARGUMENTS}" "${db}" \ 4819 "${DUMP_DIR}/${DUMP_FILE_PRE}${db}${ext}" "${DUMP_FILE_CHMOD}" \ 4820 "${COMPRESS_BIN}" "${COMPRESS_ARG}" \ 4821 "${OPENSSL_ALGO_ARG}" "${OPENSSL_PUBKEY_PEM}" \ 4822 "${MY_TMP_DIR}" 4823 )" 4824 # 4825 # Case 5/4: WRONG OPTIONS 4826 # 4827 else 4828 debug "fatal" "(???) Internal Error. Wrong mysqldump choice." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4829 _abort_on_internal_error 4830 fi 4831 4832 # 4833 # Stop time (get duration) 4834 # 4835 duration="$( get_duration "${starttime}" )" 4836 4837 4838 4839 # 4840 # Pipefail Errors 4841 # 4842 _dump_failed=0 4843 if ! MY_ERRORS="$(mysqldump_pipefail_errors "${error_statuses}")"; then 4844 _dump_failed=1 4845 4846 debug_i "fatal" "Failed\n" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4847 debug "fatal" "(RUN): ${_cnt} Error dumping ${db}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4848 4849 if ! MY_WARNINGS="$(mysqldump_pipefail_warnings "${error_statuses}")"; then 4850 debug "warn" "(RUN): ${_cnt} Warning dumping ${db}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4851 debug "warn" "${MY_WARNINGS}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4852 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4853 fi 4854 debug "fatal" "${MY_ERRORS}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4855 4856 DB_CNT_FAILED=$((DB_CNT_FAILED + 1)) 4857 MDS_FAIL_COUNT=$((MDS_FAIL_COUNT + 1)) 4858 NAGIOS_EXIT_CODE="$(merge_exit_codes "${NAGIOS_EXIT_CODE}" 2)" 4859 DB_LIST_FAILED="$( str_join "${DB_LIST_FAILED}" "," "${db}" )" 4860 # 4861 # Pipefail OK 4862 # 4863 else 4864 _dump_failed=0 4865 4866 debug_i "ok" "${duration} sec ($(get_file_size "${DUMP_DIR}/${DUMP_FILE_PRE}${db}${ext}" "m") MB)\n" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4867 debug "trace" "(RUN): ${_cnt} Dump File: ${DUMP_DIR}/${DUMP_FILE_PRE}${db}${ext}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4868 4869 if ! MY_WARNINGS="$(mysqldump_pipefail_warnings "${error_statuses}")"; then 4870 debug "warn" "(RUN): ${_cnt} Warning dumping ${db}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4871 debug "warn" "${MY_WARNINGS}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4872 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4873 fi 4874 4875 DB_CNT_DUMPED=$((DB_CNT_DUMPED + 1)) 4876 DB_LIST_DUMPED="$( str_join "${DB_LIST_DUMPED}" "," "${db}" )" 4877 fi 4878 4879 4880 4881 # 4882 # Success Handler 4883 # 4884 if [ "${_dump_failed}" = "0" ]; then 4885 4886 # 4887 # If all was good, remove required db from list 4888 # 4889 REQUIRE="$( str_remove_word "${REQUIRE}" "${db}" )" 4890 4891 4892 # 4893 # Write file info? 4894 # 4895 if [ "${DUMP_FILE_INFO}" = "1" ]; then 4896 4897 write_info_file "${DUMP_DIR}" "${DUMP_FILE_PRE}${db}${ext}" "${DUMP_FILE_CHMOD}" \ 4898 "${db}" "${DB_SIZE_B}" "${TBL_CNT_TOTAL}" "${MYSQLDUMP_ARGUMENTS}" "${duration}" \ 4899 "${COMPRESS}" "${COMPRESS_BIN}" "${COMPRESS_ARG}" \ 4900 "${ENCRYPT}" "${OPENSSL_ALGO_ARG}" "${OPENSSL_PUBKEY_PEM}" \ 4901 "${MYSQL_ARGUMENTS}" "${MYSQL_SSL_ENABLE}" "${MYSQL_SSL_STATUS}" \ 4902 "${MYSQL_SERVER_STATUS}" "${MYSQL_HOST}" "${MYSQL_PORT}" "${MYSQL_SERVER_TYPE}" "${MYSQL_SERVER}" "${MYSQL_VERSION}" 4903 4904 if [ "$?" != "0" ]; then 4905 debug "err" "(RUN): ${_cnt} Could not write info File: ${DUMP_DIR}/${DUMP_FILE_PRE}${db}${ext}.info" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4906 MDS_ERROR_COUNT=$((MDS_ERROR_COUNT + 1)) 4907 else 4908 debug "trace" "(RUN): ${_cnt} Info File: ${DUMP_DIR}/${DUMP_FILE_PRE}${db}${ext}.info" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4909 fi 4910 4911 fi 4912 fi 4913 fi 4914done 4915TIME_TOTAL_DURATION="$( get_duration "${TIME_TOTAL_START}" )" 4916 4917 4918 4919 4920################################################################################ 4921# 4922# POST PROCESSING 4923# 4924################################################################################ 4925 4926 4927############################################################ 4928# (CFG) Check required databases 4929############################################################ 4930 4931for req in ${REQUIRE}; do 4932 debug "err" "(RUN): Required database: \"${req}\" has not been dumped." "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4933 MDS_FAIL_COUNT=$((MDS_FAIL_COUNT + 1)) 4934 DB_CNT_REQ_FAILED=$((DB_CNT_REQ_FAILED + 1)) 4935 DB_LIST_REQ_FAILED="$( str_join "${DB_LIST_REQ_FAILED}" "," "${req}" )" 4936 NAGIOS_EXIT_CODE="$(merge_exit_codes "${NAGIOS_EXIT_CODE}" 2)" 4937done 4938 4939 4940 4941 4942############################################################ 4943# (OPT) TMPWATCH (Delete old files) 4944############################################################ 4945TMPWATCH_NUM_DEL="0" 4946TMPWATCH_NUM_IGN="0" 4947 4948if [ "${DELETE}" = "1" ]; then 4949 4950 # Force deletion? 4951 if [ "${DELETE_FORCE}" = "1" ]; then FORCE_ARG="--force"; else FORCE_ARG=""; fi 4952 4953 # Verbosity 4954 if [ "${DELETE_METHOD}" = "tmpwatch" ]; then TMPWATCH_OPTS="-vv"; else TMPWATCH_OPTS="--verbose=3 --showdeleted"; fi 4955 4956 TMPWATCH_RUN="$(${BIN_TMPWATCH} ${FORCE_ARG} -m "${DELETE_IF_OLDER}" "${TMPWATCH_OPTS}" "${DUMP_DIR}/" 2> "${MY_TMP_FILE_DEL}")" 4957 TMPWATCH_ERRNO="$?" 4958 TMPWATCH_ERROR="$( cat "${MY_TMP_FILE_DEL}" )" 4959 4960 if [ "${TMPWATCH_ERRNO}" != "0" ]; then 4961 debug "err" "(RUN): ${DELETE_METHOD} exit code: ${TMPWATCH_ERRNO}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4962 debug "err" "(RUN): ${DELETE_METHOD} error: ${TMPWATCH_ERROR}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4963 MDS_ERROR_COUNT=$((MDS_ERROR_COUNT + 1)) 4964 NAGIOS_EXIT_CODE="$(merge_exit_codes "${NAGIOS_EXIT_CODE}" 1)" 4965 elif [ "${TMPWATCH_ERROR}" != "" ]; then 4966 debug "warn" "(RUN): ${DELETE_METHOD} exit code: ${TMPWATCH_ERRNO}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4967 debug "warn" "(RUN): ${DELETE_METHOD} error: ${TMPWATCH_ERROR}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4968 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4969 NAGIOS_EXIT_CODE="$(merge_exit_codes "${NAGIOS_EXIT_CODE}" 1)" 4970 fi 4971 4972 # Number removed/skipped files 4973 TMPWATCH_NUM_DEL="$( echo "${TMPWATCH_RUN}" | grep -ci 'Removing file' )" 4974 TMPWATCH_NUM_IGN="$( echo "${TMPWATCH_RUN}" | grep -ci 'skipped:' )" 4975 4976 # Output of removed/skipped files 4977 TMPWATCH_TXT_DEL="$( echo "${TMPWATCH_RUN}" | grep -i 'Removing file' )" 4978 TMPWATCH_TXT_IGN="$( echo "${TMPWATCH_RUN}" | grep -i 'skipped:' )" 4979 4980 # Number of deleted files and the command itself 4981 debug "info" "(RUN): Deleting files older than $(get_tmpwatch_value "${DELETE_IF_OLDER}") $(get_tmpwatch_unit_name "${DELETE_IF_OLDER}") ... ${TMPWATCH_NUM_DEL}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4982 debug "trace" "(CFG): ${BIN_TMPWATCH} ${FORCE_ARG} -m ${DELETE_IF_OLDER} ${TMPWATCH_OPTS} ${DUMP_DIR}/" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4983 4984 4985 # Some files have been skipped! 4986 if [ "${TMPWATCH_NUM_IGN}" != "0" ] || [ "${TMPWATCH_TXT_IGN}" != "" ]; then 4987 debug "warn" "(RUN): ${DELETE_METHOD}: ${TMPWATCH_NUM_IGN} files could not be deleted:" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4988 debug "warn" "${TMPWATCH_TXT_IGN}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4989 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 4990 NAGIOS_EXIT_CODE="$(merge_exit_codes "${NAGIOS_EXIT_CODE}" 1)" 4991 fi 4992 4993 # Show deleted files 4994 debug "info|(RUN): ${DELETE_METHOD}: " "${TMPWATCH_TXT_DEL}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4995 4996 # Show full trace output 4997 debug "trace|(RUN): ${DELETE_METHOD}: " "${TMPWATCH_RUN}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 4998fi 4999 5000 5001 5002############################################################ 5003# (OPT) Nagios Plugin Log 5004############################################################ 5005 5006if [ "${NAGIOS_LOG}" = "1" ]; then 5007 5008 debug "debug" "(RUN): Writing nagios log file" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 5009 5010 { 5011 echo "[state]"; 5012 echo "success = ${NAGIOS_EXIT_CODE}"; 5013 echo "lastbak = ${TIME_TOTAL_START}"; 5014 echo "message = "; 5015 echo "missing = ${DB_LIST_REQ_FAILED}"; 5016 echo; 5017 echo "[options]"; 5018 echo "opt_log = ${LOG}"; 5019 echo "opt_com = ${COMPRESS}"; 5020 echo "opt_enc = ${ENCRYPT}"; 5021 echo "opt_del = ${DELETE}"; 5022 echo; 5023 echo "[messages]"; 5024 echo "msg_dbs = ${DB_CNT_DUMPED}"; 5025 echo "msg_ign = ${DB_CNT_IGNORED}"; 5026 echo "msg_err = ${DB_CNT_FAILED}"; 5027 echo "msg_meg = ${TOTAL_SIZE_MB}"; 5028 echo "msg_sec = ${TIME_TOTAL_DURATION}"; 5029 echo "msg_del = ${TMPWATCH_NUM_DEL}"; 5030 echo; 5031 echo "[tmpwatch]"; 5032 } > "${NAGIOS_LOG_FILE}" 5033 5034 if [ "${DELETE}" = "1" ]; then 5035 { 5036 echo "del_time = ${DELETE_IF_OLDER}"; 5037 echo "del_del = ${TMPWATCH_NUM_DEL}"; # how many files deleted 5038 echo "del_skp = ${TMPWATCH_NUM_IGN}"; # how many files skipped (due to unable to delete) 5039 } >> "${NAGIOS_LOG_FILE}" 5040 else 5041 { 5042 echo "del_time = 0"; 5043 echo "del_del = 0"; # how many files deleted 5044 echo "del_skp = 0"; # how many files skipped (due to unable to delete) 5045 } >> "${NAGIOS_LOG_FILE}" 5046 fi 5047 5048 { 5049 echo; 5050 echo "[stats]"; 5051 echo "db_dumped = ${DB_LIST_DUMPED}"; 5052 echo "db_error = ${DB_LIST_FAILED}"; 5053 echo "db_ignored = ${DB_LIST_IGNORED}"; 5054 echo; 5055 echo "[misc]"; 5056 echo "version = ${INFO_VERSION}"; # mysqldump-secure version (for checking against latest) 5057 } >> "${NAGIOS_LOG_FILE}" 5058fi 5059 5060 5061 5062############################################################ 5063# Delete temporary files 5064############################################################ 5065 5066# 5067# Delete tmp files/folders in reverse order 5068# 5069if [ "${DELETE}" = "1" ]; then 5070 if rm "${MY_TMP_FILE_DEL}" 2>/dev/null; then 5071 debug "trace" "(RUN): Deleting tmp file: ${MY_TMP_FILE_DEL}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 5072 else 5073 debug "warn" "(RUN): Cannot delete tmp file: ${MY_TMP_FILE_DEL}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 5074 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 5075 fi 5076fi 5077 5078if rm -rf "${MY_TMP_DIR}" 2>/dev/null; then 5079 debug "trace" "(RUN): Deleting tmp dir: ${MY_TMP_DIR}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 5080else 5081 debug "warn" "(RUN): Cannot delete tmp dir: ${MY_TMP_DIR}" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 5082 MDS_WARNING_COUNT=$((MDS_WARNING_COUNT + 1)) 5083fi 5084 5085 5086 5087############################################################ 5088# Exit 5089############################################################ 5090 5091 5092# Human readable output of TOTAL_SIZE (MegaBytes) 5093TOTAL_SIZE_MB="$( div "${TOTAL_SIZE_B}" "1048576" )" 5094TOTAL_SIZE_MB="$( round "${TOTAL_SIZE_MB}" "2" )" 5095 5096debug "debug" "(RUN): Dumping finished (OK: ${DB_CNT_DUMPED} dbs, IGN: ${DB_CNT_IGNORED} dbs, ERR: ${DB_CNT_FAILED}, TOTAL: ${DB_CNT_TOTAL})" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 5097debug "debug" "(RUN): Took ${TIME_TOTAL_DURATION} seconds" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 5098debug "debug" "(RUN): Total size dumped: ${TOTAL_SIZE_MB} MB" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 5099 5100 5101 5102if [ "${MDS_FAIL_COUNT}" != "0" ]; then 5103 if [ "${MDS_FAIL_COUNT}" = "1" ]; then 5104 debug "fatal" "Finished with ${MDS_FAIL_COUNT} Failures. ${DB_CNT_FAILED} failed backups (${DB_CNT_REQ_FAILED} required dbs missing)" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 5105 else 5106 debug "fatal" "Finished with ${MDS_FAIL_COUNT} Failures. ${DB_CNT_FAILED} failed backups (${DB_CNT_REQ_FAILED} required dbs missing)" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 5107 fi 5108 exit $EXIT_FAIL 5109elif [ "${MDS_ERROR_COUNT}" != "0" ]; then 5110 if [ "${MDS_ERROR_COUNT}" = "1" ]; then 5111 debug "err" "Finished with ${MDS_ERROR_COUNT} error. (Backups done successfully)" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 5112 else 5113 debug "err" "Finished with ${MDS_ERROR_COUNT} errors. (Backups done successfully)" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 5114 fi 5115 exit $EXIT_ERROR 5116elif [ "${MDS_WARNING_COUNT}" != "0" ]; then 5117 if [ "${MDS_WARNING_COUNT}" = "1" ]; then 5118 debug "warn" "Finished with ${MDS_WARNING_COUNT} warning. (Backups done successfully)" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 5119 else 5120 debug "warn" "Finished with ${MDS_WARNING_COUNT} warnings. (Backups done successfully)" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 5121 fi 5122 exit $EXIT_WARNING 5123else 5124 debug "ok" "Finished successfully" "${OUT_VERBOSITY}" "${LOG_VERBOSITY}" "${LOG_FILE}" 5125 exit $EXIT_OK 5126fi 5127