diff options
-rw-r--r-- | doc/beam.conf.5in | 15 | ||||
-rw-r--r-- | lib/beam/common.in | 23 | ||||
-rwxr-xr-x | lib/beam/mysql.sh | 215 | ||||
-rw-r--r-- | restore.in | 10 |
4 files changed, 175 insertions, 88 deletions
diff --git a/doc/beam.conf.5in b/doc/beam.conf.5in index 69277a7..9462035 100644 --- a/doc/beam.conf.5in +++ b/doc/beam.conf.5in @@ -1,5 +1,5 @@ .\" This file is part of BEAM -*- nroff -*- -.\" 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 @@ -14,7 +14,7 @@ .\" You should have received a copy of the GNU General Public License .\" along with BEAM. If not, see <http://www.gnu.org/licenses/>. .\" -.TH BEAM.CONF 5 "October 30, 2012" "BEAM" "BEAM User Reference" +.TH BEAM.CONF 5 "March 18, 2014" "BEAM" "BEAM User Reference" .SH NAME beam.conf \- configuration file for .B BEAM @@ -300,6 +300,17 @@ backup type creates a dump of a MySQL database and archives it with The database to dump and access credentials are specified using the following variables: .TP +.BR \fIitem\fB_alldb = single | monolithic | split | individual +Determines how to dump databases if the \fIitem\fB_database\fR +(see below) variable is not set. The value \fBsingle\fR or +\fBmonolithic\fR means dump all databases to a single file named +after the \fIitem\fR. This is the default. The value \fBsplit\fR +or \fBindividual\fR instructs \fBbeam\fR to dump each database into +a separate file, named +.nh +\fIitem\fB-\fIdbname\fB-\fIweek\fB-\fIround\fB-\fIlevel\fB.\fIsuffix\fR +.hy +.TP .BR \fIitem\fB_database = \fISTRING\fR The database name. If this variable is empty, all databases will be dumped. 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 +} + @@ -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 @@ -121,9 +121,9 @@ if [ -z "$week" ]; then fi if [ -z "$round" ]; then - round=$(find $backup_archive_dir \ + round=$(beam_exec find $backup_local_archive_dir \ -regex '.*-'$week'-[0-9][0-9]*-[0-9][0-9]*\..*' \ - -printf '%f\n' | + -printf '%f\\n' | sed 's/.*-'$week'-\([0-9][0-9]*\)-[0-9][0-9]*\..*/\1/' | sort +0 -1 | tail -1) @@ -131,9 +131,9 @@ if [ -z "$round" ]; then fi if [ -z "$level" ]; then - level=$(find $backup_archive_dir \ + level=$(beam_exec find $backup_local_archive_dir \ -regex '.*-'$week-$round'-[0-9][0-9]*\..*' \ - -printf '%f\n' | + -printf '%f\\n' | sed 's/.*-'$week-$round'-\([0-9][0-9]*\)\..*/\1/' | sort +0 -1 | tail -1) |