Commit 12b28ddc authored by Sven Greiner's avatar Sven Greiner
Browse files

Various fixes and cleanup

parent fa40a73a
#!/bin/bash
# backup all available MySQL databases via mydumper
# and upload them to an (s)ftp server
# backups can be optionally compressed and encrypted
#
# sftp note: ssh private/public key with no password is required
# if not using pwauth
################################################################################
##### CONFIGURATION
# myftpdumper - Create and upload MySQL backups
#
# Backup all available MySQL databases via mydumper and optionally upload them
# to an (s)ftp server. Backups can be compressed and encrypted.
#
# sftp note: ssh private/public key with no password is required if pwauth is
# not used.
################################################################################
#### BEGIN CONFIGURATION #######################################################
### system settings
declare -r BACKUP_PATH="/root/mydumper"
declare -r ADMINMAIL="foo@example.com"
# Absolute path to local backup directory
declare -r BACKUP_PATH=""
# Send mail to this address in case of any errors. No mail if empty.
declare -r ADMINMAIL=
# Keep so many backups or all if 0
declare -r NUMBACKUPS=30
# Combine tables of a database in single file
declare -r USETAR=1
# compression tools like gzip, bzip2, xz, lzop
# empty for no compression. parameters allowed
# Compression utility (like gzip, bzip2, xz, lzop), parameters allowed
# Disable compression if empty
declare -r COMPRESS="xz -T0"
# The umask that is used for the backup. Leave empty to keep unchanged
declare -r UMASK=0077
### MySQL settings
declare -r DB_HOST="localhost"
declare -r DB_USER="root"
declare -r DB_HOST=""
declare -r DB_USER=""
declare -r DB_PASS=""
declare -r DB_EXCLUDE='^(?!(mysql|phpmyadmin|information_schema|performance_schema))'
### Remote server settings
declare -r FTP_HOST="example.com"
# Type of ftp connection: ftp, ftps, sftp
# Leave empty to disable upload
declare -r FTP_TYPE=
declare -r FTP_HOST=""
declare -r FTP_USER=""
declare -r FTP_PASS=""
declare -r FTP_TYPE="sftp" # ftp, ftps, sftp - leave empty if not desired
declare -r FTP_PORT="" # leave empty for standard protocol port
declare -r FTP_DIR="path/on/ftp"
declare -r FTP_PORT= # empty for default
declare -r FTP_DIR=""
declare -r FTP_NUMBACKUPS=90
### GPG settings
declare -r GPG_KEYID="" # GPG key I
declare -r GPG_PASS="" # GPG symmetrical passphrase, if not using GPG_KEYID
# GPG key ID used for encryption starting with "0x" (preferred)
# or passphrase for symmetric encryption or empty (no encryption).
declare -r GPG_KEYID=
declare -r GPG_PASS=
################################################################################
info() {
echo "INFO: $1"
}
......@@ -50,7 +81,7 @@ warn() {
error() {
echo "ERROR: $1" >&2
if [ -n "$ADMINMAIL" ] && [[ -n "$2" ]]; then
if wants_mail && [[ -n "$2" ]]; then
mail -s "MySQL BACKUP FAILED" "$ADMINMAIL" <<- EOF
Date: $(date --rfc-3339=seconds)
Hostname: $(hostname)
......@@ -88,6 +119,11 @@ wants_encryption() {
}
check_prerequisites() {
# check mail first because all further errors might be mailed
if wants_mail; then
require_command "mail" 1
fi
[[ -z "$BACKUP_PATH" ]] && error "BACKUP_PATH not set"
[[ -z "$DB_HOST" ]] && error "DB_HOST not set"
[[ -z "$DB_USER" ]] && error "DB_USER not set"
......@@ -96,30 +132,29 @@ check_prerequisites() {
require_command "mydumper"
if wants_mail; then
require_command "mail" 1
fi
if wants_tar; then
require_command "tar"
fi
if wants_upload; then
require_command "lftp"
fi
if wants_compression; then
require_command ${COMPRESS%% *}
fi
if wants_encryption; then
require_command "gpg"
if [[ -n "$GPG_KEYID" ]] {
gpg --list-keys $GPG_KEYID &> /dev/null
if [[ $? -ne 0 ]]; then
error "GPG key \"$GPG_KEYID\" not available"
fi
}
if [[ -n "$GPG_KEYID" ]]; then
gpg --list-keys $GPG_KEYID &> /dev/null \
|| error "GPG key \"$GPG_KEYID\" not available"
fi
fi
if wants_upload; then
require_command "lftp"
[[ -z "$FTP_HOST" ]] && error "FTP_HOST not set"
[[ -z "$FTP_USER" ]] && error "FTP_USER not set"
[[ -z "$FTP_PASS" ]] && error "FTP_PASS not set"
[[ -z "$FTP_DIR" ]] && error "FTP_DIR not set"
fi
}
......@@ -131,6 +166,7 @@ prepare() {
declare -rg date=$(date +"%Y%m%d-%H%M%S")
declare -rg backupdir="$BACKUP_PATH/$date"
mkdir "$backupdir" \
|| error "Failed to create $backupdir"
}
......@@ -147,28 +183,27 @@ delete_old_backups() {
info "Delete local backups older than $NUMBACKUPS latest backups"
for dir in $(ls -t1 "$BACKUP_PATH" | tail -n +$NUMBACKUPS); do
info "Delete backup \"$dir\""
rm -r "$BACKUP_PATH/$dir" &> /dev/null
[[ $? -ne 0 ]] \
&& error "Deletion of \"$dir\" failed."
rm -r "$BACKUP_PATH/$dir" &> /dev/null \
|| error "Deletion of \"$dir\" failed."
done
fi
}
exec_ftp() {
if [ -n "$FTP_PORT" ]; then
lftp -p $FTP_PORT -u $FTP_USER,$FTP_PASS $FTP_TYPE://$FTP_HOST -e "$1" 2> /dev/null
else
lftp -u $FTP_USER,$FTP_PASS $FTP_TYPE://$FTP_HOST -e "$1" 2> /dev/null
fi
[ $? -ge 1 ] \
&& error "Failed to execute command on remote server: $1"
}
backup () {
info "Starting local MySQL backup to $backupdir"
now=$(date --rfc-3339=seconds)
mydumper -u "$DB_USER" -p "$DB_PASS" -h "$DB_HOST" --regex "$DB_EXCLUDE" -o "$backupdir"
[ $? -ge 1 ] \
&& error "Backup failed during execution of mydumper!"
if [[ $? -ne 0 ]]; then
touch "$backupdir/incomplete"
error "Backup failed during execution of mydumper!"
fi
# add timestamp to the sql files
for f in "$backupdir/"*.sql; do
echo -e "\n/* $now */" >> "$f"
done
}
compression() {
......@@ -178,7 +213,7 @@ compression() {
# format: db.table.sql or db-schema-create.sql
dbs=$(ls *.sql | cut -d "." -f 1 | cut -d "-" -f 1 | sort | uniq)
for db in $dbs; do
info "compressing: $db"
info "Compressing: $db"
if wants_tar; then
tar cf "$db.tar" "$db"[.-]* \
&& rm "$db"[.-]*.sql
......@@ -196,62 +231,72 @@ compression() {
}
encryption() {
### Encryption
if wants_encryption; then
info "Starting encryption"
if [[ -n "$GPG_KEYID" ]]; then
info "Encrypt backup with GPG key \"$GPG_KEYID\""
else
info "Encrypt using symmetric encryption"
fi
cd "$backupdir"
for i in *; do
if [ -n "$GPG_KEYID" ]; then
info "Encrypt backup $i with GPG key \"$GPG_KEYID\""
gpg -e -r "$GPG_KEYID" "$i" \
&& rm "$i"
[[ $? -ne 0 ]] \
&& error "Encryption of \"$i\" failed."
for x in *; do
if [[ -n "$GPG_KEYID" ]]; then
gpg --batch --encrypt --recipient "$GPG_KEYID" --trust-model always "$x" \
&& rm "$x"
else
info "Encrypt backup $i with passphrase"
echo "$GPG_PASS" \
| gpg -c --batch --passphrase-fd 0 --cipher-algo AES256 "$i" \
echo "$GPG_PASS" | gpg --batch --symmetric --passphrase-fd 0 --cipher-algo AES256 "$x" \
&& rm "$i"
[[ $? -ne 0 ]] \
&& error "Encryption of \"$i\" failed."
fi
# error because you probably do not want to upload unencrypted backups
[[ $? -ne 0 ]] \
&& error "Encryption of \"$x\" failed."
done
cd - &> /dev/null
fi
}
exec_ftp() {
if [[ -n "$FTP_PORT" ]]; then
  • Die Redundanz kann man sicher vermeiden, indem man -p $FTP_PORT in eine Variable schreibt oder sie leer lässt und stumpf in den Befehl einfügt.

Please register or sign in to reply
lftp -p $FTP_PORT -u $FTP_USER,$FTP_PASS $FTP_TYPE://$FTP_HOST -e "$1" 2> /dev/null
else
lftp -u $FTP_USER,$FTP_PASS $FTP_TYPE://$FTP_HOST -e "$1" 2> /dev/null
fi
[[ $? -ne 0 ]] \
&& error "Failed to execute command on remote server: $1"
}
upload() {
if wants_upload; then
### FTP: directory permission check
# FTP: directory permission check
ftpmkdir=$(exec_ftp "mkdir -p $FTP_DIR/$date; exit")
if [[ "$ftpmkdir" != *"mkdir OK"* ]]; then
error "Failed create $FTP_DIRnoslash/$date on remote server"
error "Failed create \"$FTP_DIR/$date\" on remote server"
fi
### FTP: delete old backups
# FTP: delete old backups
info "Delete old backups on FTP..."
ftpfiles=$(exec_ftp "cd $FTP_DIR; nlist; exit")
# filter files starting with a dot
ftpfiles=( $(echo $ftpfiles | sed 's,\.[A-Za-z0-9_\/\.]* , ,g') )
# find old backups
ftpfilesdelete=()
while [ ${#ftpfiles[@]} -ge $FTP_NUMBACKUPS ]; do
while [[ ${#ftpfiles[@]} -ge $FTP_NUMBACKUPS ]]; do
ftpfilesdelete+=(${ftpfiles[0]})
ftpfiles=("${ftpfiles[@]:1}")
done
# delete on ftp
[ ${#ftpfilesdelete[@]} -ge 1 ] \
[[ ${#ftpfilesdelete[@]} -ge 1 ]] \
&& ftpfilesdelete=${ftpfilesdelete[@]} \
&& exec_ftp "cd $FTP_DIR; rm -r $ftpfilesdelete; exit"
### FTP: upload
# FTP: upload
info "Upload to FTP..."
exec_ftp "cd $FTP_DIR; mirror -R $backupdir; exit"
Please register or sign in to reply
else
warn "No FTP backup configured"
fi
}
check_prerequisites
set_umask
prepare
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment