From 10d30373c6fdf0dd23f16251fa2302c18b7eef97 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Tue, 18 Mar 2014 23:17:42 +0200 Subject: Allow for dumping each MySQL database into a separate file. * lib/beam/common.in (load_config): Set beam_rsh and backup_local_archive_dir. (beam_exec): New function. * lib/beam/mysql.sh (dump_mysql_db) (restore_mysql_db): New functions. (mysql_backup,mysql_restore): Dump databases individually, depending on the value of _alldb variable. * restore.in: Use beam_exec to run find. * doc/beam.conf.5in: Document changes. --- lib/beam/common.in | 23 +++++- lib/beam/mysql.sh | 215 +++++++++++++++++++++++++++++++++-------------------- 2 files changed, 157 insertions(+), 81 deletions(-) (limited to 'lib/beam') diff --git a/lib/beam/common.in b/lib/beam/common.in index e99433e..4f2184b 100644 --- a/lib/beam/common.in +++ b/lib/beam/common.in @@ -1,6 +1,6 @@ #! /bin/sh # This file is part of BEAM -# Copyright (C) 2012 Sergey Poznyakoff +# Copyright (C) 2012-2014 Sergey Poznyakoff # # BEAM is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -76,7 +76,7 @@ tarcode() { } load_config() { - local delayed_exit + local delayed_exit remote test -z "$BEAM_CONFIG" && BEAM_CONFIG=@SYSCONFDIR@/beam.conf if [ -r $BEAM_CONFIG ]; then @@ -130,6 +130,25 @@ $type" . @LIBDIR@/beam/s3.sh prologue_hook="s3_mount $prologue_hook" fi + + remote=${backup_archive_dir%%:*} + if [ "$remote" != "$backup_archive_dir" ]; then + beam_rsh="${backup_rsh:-ssh} $remote" + backup_local_archive_dir=${backup_archive_dir#*:} + else + beam_rsh= + backup_local_archive_dir=$backup_archive_dir + fi +} + +beam_exec() { + if [ -z "$beam_rsh" ]; then + set -- $(echo "$@" | sed 's/\\\\\([bcfnrtv0]\)/\\\1/g') + "$@" + else + set -- $(echo "$@" | sed 's/\\\\\([bcfnrtv0]\)/\\\1/g;s/[]\[\\\*]/\\&/g') + $beam_rsh "$@" + fi } runhook() { diff --git a/lib/beam/mysql.sh b/lib/beam/mysql.sh index 185fa48..e8ec32c 100755 --- a/lib/beam/mysql.sh +++ b/lib/beam/mysql.sh @@ -1,6 +1,6 @@ #! /bin/sh # This file is part of BEAM -# Copyright (C) 2012 Sergey Poznyakoff +# Copyright (C) 2012-2014 Sergey Poznyakoff # # BEAM is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -17,102 +17,159 @@ # Configuration keywords: # -# item_type=mysql [mandatory] -# item_database=STRING [optional] -# item_defaults_file=STRING [optional] +# item_type=mysql [mandatory] +# item_database=STRING [optional] +# item_defaults_file=STRING [optional] +# item_alldb=single|monolithic|split|individual [optional] # # mysql_check item mysql_check() { - return 0 + return 0 } # mysql_list item prefix mysql_list() { - local database - - eval database=\$${1}_database - if [ -z "$database" ]; then - echo "${2}all MySQL databases" - else - echo "${2}MySQL database $database" - fi + local database + + eval database=\$${1}_database + if [ -z "$database" ]; then + echo "${2}all MySQL databases" + else + echo "${2}MySQL database $database" + fi } -# mysql_backup item -mysql_backup() { - local database +# dump_mysql_db cmd stem +dump_mysql_db() { + if [ -z "$dry_run" ]; then + $1 $db > $backup_tmp_dir/$2-$week-$round-$level + else + echo "$1 $db > $backup_tmp_dir/$2-$week-$round-$level" + fi - eval database=\$${1}_database - if [ -z "$database" ]; then - logit "backing up all MySQL databases" - else - logit "backing up MySQL database $database" - fi - cmd="mysqldump" - eval defaults_file=\$${1}_defaults_file - if [ -n "$defaults_file" ]; then - cmd="$cmd --defaults-file=$defaults_file" - fi - cmd="$cmd --add-drop-database" - if test -z "$database"; then - cmd="$cmd --all-databases" - else - cmd="$cmd --databases" - fi - if [ -z "$dry_run" ]; then - $cmd $database > $backup_tmp_dir/$1-$week-$round-$level - else - echo "$cmd $database > $backup_tmp_dir/$1-$week-$round-$level" - fi + if [ $? -ne 0 ]; then + tarerror=$((tarerror + 1)) + logit "failed" + else + logit "creating $2-$week-$round-$level.$tar_suffix" + $dry_run tar $verbose $taroptions \ + -f $backup_archive_dir/$2-$week-$round-$level.$tar_suffix \ + -C $backup_tmp_dir $2-$week-$round-$level + tarcode $? + $dry_run rm $backup_tmp_dir/$2-$week-$round-$level + fi +} - if [ $? -ne 0 ]; then - tarerror=$((tarerror + 1)) - logit "failed" - else - logit "creating $1-$week-$round-$level.$tar_suffix" +restore_mysql_db() { + local u + + logit "restoring MySQL database $1" + u=$(umask) + trap "umask $u" 1 2 3 13 15 + umask 077 $dry_run tar $verbose $taroptions \ - -f $backup_archive_dir/$1-$week-$round-$level.$tar_suffix \ - -C $backup_tmp_dir $1-$week-$round-$level - tarcode $? - $dry_run rm $backup_tmp_dir/$1-$week-$round-$level - fi + -f $backup_archive_dir/$1-$week-$round-$level.$tar_suffix + e=$? + tarcode $e + if [ $e -eq 0 ]; then + logit "restoring database from the dump" + # Stupid lossage: cannot give -A option here, because with it mysql + # refuses to understand defaults-file. + cmd="mysql" + eval defaults_file=\$${1}_defaults_file + if [ -n "$defaults_file" ]; then + cmd="$cmd --defaults-file=$defaults_file" + fi + if [ -n "$dry_run" ]; then + echo "$cmd < $1-$week-$round-$level" + elif [ -r $1-$week-$round-$level ]; then + $cmd < $1-$week-$round-$level > db-$1.log + if grep ERROR db-$1.log >/dev/null; then + error "errors occurred during restore; see db-$1.log for details" + error "dump preserved in file $1-$week-$round-$level" + tarerror=$((tarerror + 1)) + else + rm $1-$week-$round-$level + fi + fi + fi + umask $u + trap - 1 2 3 13 15 } -mysql_restore() { - local u database +# mysql_backup item +mysql_backup() { + local creds cmd database alldb db stem - eval database=\$${1}_database - logit "restoring MySQL database $database" - u=$(umask) - trap "umask $u" 1 2 3 13 15 - umask 077 - $dry_run tar $verbose $taroptions \ - -f $backup_archive_dir/$1-$week-$round-$level.$tar_suffix - e=$? - tarcode $e - if [ $e -eq 0 ]; then - logit "restoring database from the dump" - # Stupid lossage: cannot give -A option here, because with it mysql - # refuses to understand defaults-file. - cmd="mysql" + eval database=\$${1}_database + if [ -z "$database" ]; then + logit "backing up all MySQL databases" + else + logit "backing up MySQL database $database" + fi + cmd="mysqldump" eval defaults_file=\$${1}_defaults_file if [ -n "$defaults_file" ]; then - cmd="$cmd --defaults-file=$defaults_file" + creds="--defaults-file=$defaults_file" + cmd="$cmd $creds" fi - if [ -n "$dry_run" ]; then - echo "$cmd < $1-$week-$round-$level" - elif [ -r $1-$week-$round-$level ]; then - $cmd < $1-$week-$round-$level > db-$1.log - if grep ERROR db-$1.log >/dev/null; then - error "errors occurred during restore; see db-$1.log for details" - error "dump preserved in file $1-$week-$round-$level" - tarerror=$((tarerror + 1)) - else - rm $1-$week-$round-$level - fi + cmd="$cmd --add-drop-database" + cmd="$cmd --single-transaction" + + if test -z "$database"; then + eval alldb=\$${1}_alldb + case $alldb in + single|monolithic) + cmd="$cmd --all-databases";; + split|individual) + alldb=split + cmd="$cmd --databases" + database=$(mysql $creds -e "show databases" -B --skip-column-names);; + "") cmd="$cmd --all-databases";; + *) error "unknown value: ${1}_alldb=$alldb, assuming 'single'" + cmd="$cmd --all-databases";; + esac + else + cmd="$cmd --databases" + fi + + if [ -z "$database" ]; then + dump_mysql_db "$cmd" "$1" + else + for db in $database + do + if [ "$alldb" = split ]; then + stem=$1-$db + logit "dumping $db" + else + stem=$1 + fi + dump_mysql_db "$cmd" "$stem" + done fi - fi - umask $u - trap - 1 2 3 13 15 } + +mysql_restore() { + local database dbname remote + + eval database=\$${1}_database + if test -z "$database"; then + eval alldb=\$${1}_alldb + case $alldb in + split|individual) + beam_exec find $backup_local_archive_dir \ + -name $1-'*'-$week-$round-$level.$tar_suffix \ + -printf '%f\\n' | \ + while read file + do + restore_mysql_db $(expr "$file" : "$1-\(.[^-]*\)-.*") + done + ;; + *) restore_mysql_db $1 + esac + else + restore_mysql_db $database + fi +} + -- cgit v1.2.1