diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2012-05-17 14:55:57 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2012-05-17 15:05:46 +0300 |
commit | 6b8fa542771cc9a93a9ecdfb20da9cea0781f1c4 (patch) | |
tree | e9998bd888fb29829e013a2de825a74b6e8db87d /lib | |
download | beam-6b8fa542771cc9a93a9ecdfb20da9cea0781f1c4.tar.gz beam-6b8fa542771cc9a93a9ecdfb20da9cea0781f1c4.tar.bz2 |
Initial import
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile.am | 1 | ||||
-rw-r--r-- | lib/backup/.gitignore | 1 | ||||
-rw-r--r-- | lib/backup/Makefile.am | 11 | ||||
-rw-r--r-- | lib/backup/common.in | 86 | ||||
-rwxr-xr-x | lib/backup/fs.sh | 92 | ||||
-rwxr-xr-x | lib/backup/postgres.sh | 72 |
6 files changed, 263 insertions, 0 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am new file mode 100644 index 0000000..b26ee9a --- /dev/null +++ b/lib/Makefile.am @@ -0,0 +1 @@ +SUBDIRS=backup
\ No newline at end of file diff --git a/lib/backup/.gitignore b/lib/backup/.gitignore new file mode 100644 index 0000000..5621a6e --- /dev/null +++ b/lib/backup/.gitignore @@ -0,0 +1 @@ +common.sh diff --git a/lib/backup/Makefile.am b/lib/backup/Makefile.am new file mode 100644 index 0000000..ec4cb91 --- /dev/null +++ b/lib/backup/Makefile.am @@ -0,0 +1,11 @@ +libbackupdir=$(libdir)/backup +libbackup_SCRIPTS=\ + common.sh\ + fs.sh\ + postgres.sh +EXTRA_DIST=\ + common.in\ + fs.sh\ + postgres.sh +DISTCLEANFILES=common.sh +include $(top_srcdir)/Make.rules diff --git a/lib/backup/common.in b/lib/backup/common.in new file mode 100644 index 0000000..ab80204 --- /dev/null +++ b/lib/backup/common.in @@ -0,0 +1,86 @@ +#! /bin/bash + +# Force C locale +LC_ALL=C +export LC_ALL + +prologue_hook= +epilogue_hook= + +# User configuration variables +backup_tar_options= +backup_suffix= +backup_archive_dir= +backup_snapshot_dir= +backup_verbose= +backup_logfile="/var/log/backup" + +error() { + echo >&2 $0: $* +} + +logit() { + echo `date`: $* +} + +abend() { + ec=$1 + shift + error $@ + exit $ec +} + +tarcode() { + case $1 in + 0) echo "`date`: success";; + 1) echo "`date`: some files changed while being archived";; + 2) echo "`date`: fatal error occurred, but trying to continue anyway" + tarerror=$((tarerror + 1));; + *) echo "`date`: unexpected error code $1" + tarerror=$((tarerror + 1)); + esac +} + +load_config() { + local delayed_exit + + test -z "$BACKUP_CONFIG" && BACKUP_CONFIG=@SYSCONFDIR@/backup.conf + if [ -r $BACKUP_CONFIG ]; then + . $BACKUP_CONFIG + else + abend 1 "configuration file $BACKUP_CONFIG does not exist or is unreadable" + fi + + if [ -z "$backup_items" ]; then + abend 1 "backup_items not specified" + fi + + delayed_exit= + loaded_types= + for item in $backup_items + do + eval type=\$${item}_type + if [ -z "$type" ]; then + error "${item}_type not set" + delayed_exit=1 + continue + fi + + if echo "$loaded_types" | grep -wq $type; then + : + elif [ -x $libdir/${type}.sh ]; then + . $libdir/${type}.sh || delayed_exit=1 + loaded_types="$loaded_files +$type" + else + error "$libdir/${type}.sh not found" + delayed_exit=1 + fi + + ${type}_check $item || delayed_exit=1 + done + + test -n "$delayed_exit" && abend 1 "aborting" + + tar_suffix=${backup_suffix:-.tar} +} diff --git a/lib/backup/fs.sh b/lib/backup/fs.sh new file mode 100755 index 0000000..3950e37 --- /dev/null +++ b/lib/backup/fs.sh @@ -0,0 +1,92 @@ +#! /bin/bash + +# initdb item +# Initializes snapshot for the given basename. +initdb() { + local filename + + if [ -n "$dry_run" ]; then + logit "initializing snapshot for $1" + return + fi + + if [ $level -eq 0 ]; then + filename=$backup_snapshot_dir/$1-$week-$round-$level.db + test -r $filename && rm $filename + else + if [ $level -eq 1 ]; then + filename=$backup_snapshot_dir/$1-$week-0-0.db + else + filename=$backup_snapshot_dir/$1-$week-$round-$((level - 1)).db + fi + if [ -r $filename ]; then + cp $filename $backup_snapshot_dir/$1-$week-$round-$level.db + else + abend 1 "previous snapshot file $filename not found; cannot backup at level $level" + exit 1 + fi + fi +} + +# fs_check item +fs_check() { + local rc=0 + + eval root=\$${1}_dir + eval files=\$${1}_files + + test -z "$root" && rc=1 && error "${1}_dir not set" + test -z "$files" && rc=1 && error "${1}_files not set" + return $rc +} + +# fs_backup item +fs_backup() { + local basename text root files + + basename=$1-$week-$round-$level + eval text=\$${1}_text + eval root=\$${1}_dir + eval files=\$${1}_files + + test -z "$root" && abend 1 "${1}_dir not set" + test -z "$files" && abend 1 "${1}_files not set" + test -z "$text" && text="$1" + initdb $1 + logit "backing up $text ($basename.$tar_suffix)" + $dry_run tar $verbose $taroptions \ + -c -f $backup_archive_dir/$basename.$tar_suffix \ + --listed=$backup_snapshot_dir/$basename.db \ + -C $root $files + tarcode $? +} + +# fs_restore item +fs_restore() { + local i text root files tarcommand + + eval text=\$${1}_text + eval root=\$${1}_dir + eval files=\$${1}_files + + test -z "$root" && abend 1 "${1}_dir not set" + test -z "$files" && abend 1 "${1}_files not set" + test -z "$text" && text="$1" + + tarcommand="tar $verbose $taroptions -C $root --listed-incremental=/dev/null -f" + + logit "restoring $text" + logit "restoring from level 0 backup" + + $dry_run $tarcommand $backup_archive_dir/$1-$week-0-0.$tar_suffix + tarcode $? + + for i in $(seq 1 $level) + do + logit "restoring from the $round/$i backup" + $dry_run $tarcommand $backup_archive_dir/$1-$week-$round-$i.tar.bz2 + tarcode $? + done + logit "finished restoring $text" +} + diff --git a/lib/backup/postgres.sh b/lib/backup/postgres.sh new file mode 100755 index 0000000..953c467 --- /dev/null +++ b/lib/backup/postgres.sh @@ -0,0 +1,72 @@ +#! /bin/bash + +# postgres_check item +postgres_check() { + eval database=\$${1}_database + test -z "$database" && error "${1}_database not set" && return 1 + return 0 +} + +# postgres_backup item +postgres_backup() { + local database + + logit "backing up PostgreSQL $1" + eval database=\$${1}_database + test -z "$database" && abend 1 "${1}_database not set" + if [ -z "$dry_run" ]; then + su postgres -c "pg_dump $verbose $database" > $backup_snapshot_dir/$1-$week-$round-$level + else + echo "su postgres -c \"pg_dump $verbose $database\" > $backup_snapshot_dir/$1-$week-$round-$level" + fi + + if [ $? -ne 0 ]; then + tarerror=$((tarerror + 1)) + echo >&2 "`date`: failed" + else + echo "`date`: creating $1-$week-$round-$level.$tar_suffix" + $dry_run tar $verbose $taroptions \ + -f $backup_archive_dir/$1-$week-$round-$level.$tar_suffix \ + -C $backup_snapshot_dir $1-$week-$round-$level + tarcode $? + $dry_run rm $snapshotdir/dbdump-$week-$round-$level + fi +} + +postgres_restore() { + local u database + + eval database=\$${1}_database + logit "restoring PostgreSQL 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" + if [ -n "$dry_run" ]; then + cat <<-EOT + su postgres -c "dropdb $database" + su postgres -c "createdb $database" + su postgres -c "psql -d $database -f $1-$week-$round-$level" + rm $1-$week-$round-$level +EOT + elif [ -r $1-$week-$round-$level ]; then + su postgres -c "dropdb $database" + su postgres -c "createdb $database" + su postgres -c "psql -d $database -f $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 +} |