Commit fa40a73a authored by Fjen Undso's avatar Fjen Undso
Browse files

split code into seperate functions

idea by SammysHP
parent 422302cc
......@@ -6,150 +6,258 @@
# sftp note: ssh private/public key with no password is required
# if not using pwauth
##### BEGIN SETTINGS
################################################################################
##### CONFIGURATION
### system settings
declare -r LOCALDIR="/root/mydumper"
declare -r BACKUP_PATH="/root/mydumper"
declare -r ADMINMAIL="foo@example.com"
# Keep so many backups or all if 0
declare -r NUMBACKUPS=30
# tar all individual tables from one database
# 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
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 MYHOST="localhost"
declare -r MYUSER="root"
declare -r MYPASS=""
declare -r EXLUDEDBS='^(?!(mysql|phpmyadmin|information_schema|performance_schema))'
### ftp/sftp settings
declare -r FTPHOST="example.com"
declare -r FTPUSER=""
declare -r FTPPASS=""
declare -r FTPTYPE="sftp" # ftp, ftps, sftp - leave empty if not desired
declare -r FTPPORT="" # leave empty for standard protocol port
declare -r FTPDIR="path/on/ftp"
declare -r FTPNUMBACKUPS=90
### gpg settings
declare -r GPGKEYID="" # gpg key id
declare -r GPGPASS="" # gpg symmetrical passphrase, if not using GPGKEYID
##### END SETTINGS
fail() {
if [ -n "$ADMINMAIL" ]; then
### Mail admin on error
tmplogfile=`mktemp`
echo "Date: $(date)" >> $tmplogfile
echo "Hostname: $(hostname)" >> $tmplogfile
echo "Failed with message $1" >> $tmplogfile
mail -s "MySQL BACKUP FAILED" "$ADMINMAIL" < $tmplogfile
rm $tmplogfile
### MySQL settings
declare -r DB_HOST="localhost"
declare -r DB_USER="root"
declare -r DB_PASS=""
declare -r DB_EXCLUDE='^(?!(mysql|phpmyadmin|information_schema|performance_schema))'
### Remote server settings
declare -r FTP_HOST="example.com"
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_NUMBACKUPS=90
### GPG settings
declare -r GPG_KEYID="" # GPG key I
declare -r GPG_PASS="" # GPG symmetrical passphrase, if not using GPG_KEYID
################################################################################
info() {
echo "INFO: $1"
}
warn() {
echo "WARN: $1" >&2
}
error() {
echo "ERROR: $1" >&2
if [ -n "$ADMINMAIL" ] && [[ -n "$2" ]]; then
mail -s "MySQL BACKUP FAILED" "$ADMINMAIL" <<- EOF
Date: $(date --rfc-3339=seconds)
Hostname: $(hostname)
Failed with message: $1
EOF
fi
echo "$1" >&2
exit 1
}
execftp() {
if [ -n "$FTPPORT" ]; then
lftp -p $FTPPORT -u $FTPUSER,$FTPPASS $FTPTYPE://$FTPHOST -e "$1" 2> /dev/null
require_command() {
if [[ ! "$(which $1)" ]]; then
error "Prerequisite \"$1\" not found in PATH" $2
fi
}
wants_mail() {
[[ -n "$ADMINMAIL" ]]
}
wants_tar() {
[[ "$USE_TAR" -eq 1 ]]
}
wants_upload() {
[[ -z "$FTP_TYPE" ]]
}
wants_compression() {
[[ -n "${COMPRESS%% *}" ]]
}
wants_encryption() {
[[ -n "$GPG_KEYID$GPG_PASS" ]]
}
check_prerequisites() {
[[ -z "$BACKUP_PATH" ]] && error "BACKUP_PATH not set"
[[ -z "$DB_HOST" ]] && error "DB_HOST not set"
[[ -z "$DB_USER" ]] && error "DB_USER not set"
[[ -z "$DB_PASS" ]] && error "DB_PASS not set"
[[ -z "$DB_EXCLUDE" ]] && error "DB_EXCLUDE not set"
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
}
fi
}
prepare() {
if [[ ! -d "$BACKUP_PATH" ]]; then
mkdir -p "$BACKUP_PATH"\
|| error "Failed to create \"$BACKUP_PATH\""
fi
declare -rg date=$(date +"%Y%m%d-%H%M%S")
declare -rg backupdir="$BACKUP_PATH/$date"
mkdir "$backupdir" \
|| error "Failed to create $backupdir"
}
set_umask() {
if [[ -n "$UMASK" ]]; then
info "Setting umask from $(umask) to $UMASK"
umask "$UMASK"
fi
}
delete_old_backups() {
if [[ "$NUMBACKUPS" -gt 0 ]]; then
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."
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 $FTPUSER,$FTPPASS $FTPTYPE://$FTPHOST -e "$1" 2> /dev/null
lftp -u $FTP_USER,$FTP_PASS $FTP_TYPE://$FTP_HOST -e "$1" 2> /dev/null
fi
[ $? -ge 1 ] \
&& fail "Error: ftp command failed: $1"
&& error "Failed to execute command on remote server: $1"
}
backup () {
info "Starting local MySQL backup to $backupdir"
mydumper -u "$DB_USER" -p "$DB_PASS" -h "$DB_HOST" --regex "$DB_EXCLUDE" -o "$backupdir"
[ $? -ge 1 ] \
&& error "Backup failed during execution of mydumper!"
}
### Check prerequisites
for i in mydumper lftp mail tar gpg ${COMPRESS%% *}; do
if [ ! "$(which $i)" ]; then
fail "Error: prerequisite $i not found in PATH"
compression() {
if wants_tar || wants_compression; then
info "Starting compression"
cd "$backupdir"
# 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"
if wants_tar; then
tar cf "$db.tar" "$db"[.-]* \
&& rm "$db"[.-]*.sql
[[ $? -ne 0 ]] \
&& error "Tar of \"$db\" failed."
fi
if wants_compression; then
$COMPRESS "$db"[.-]*
[[ $? -ne 0 ]] \
&& error "Compression of \"$db\" failed."
fi
done
cd - &> /dev/null
fi
done
### Check local directory
if [ ! -d "$LOCALDIR" ]; then
mkdir -p "$LOCALDIR" \
|| fail "Error: failed to create $LOCALDIR"
fi
### Delete local old backups
echo "### Delete local old backups"
for dir in $(ls -t1 "$LOCALDIR" | tail -n +$NUMBACKUPS); do
echo "delete: $dir"
rm -r "$LOCALDIR/$dir"
done
### MySQL backup
echo "### MySQL Backup..."
date=$(date +"%Y%m%d-%H%M%S")
backupdir="$LOCALDIR/$date"
mkdir "$backupdir" \
|| fail "Error: failed to create $backupdir"
mydumper -u "$MYUSER" -p "$MYPASS" -h "$MYHOST" --regex "$EXLUDEDBS" -o "$backupdir"
[ $? -ge 1 ] \
&& fail "Error: mydumper failed"
### Compression
echo "### Compression..."
cd "$backupdir"
# 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
echo "compress: $db"
if [ "$USETAR" -eq 1 ]; then
tar cf "$db.tar" "$db"[.-]* \
&& rm "$db"[.-]*.sql
}
encryption() {
### Encryption
if wants_encryption; then
info "Starting encryption"
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."
else
info "Encrypt backup $i with passphrase"
echo "$GPG_PASS" \
| gpg -c --batch --passphrase-fd 0 --cipher-algo AES256 "$i" \
&& rm "$i"
[[ $? -ne 0 ]] \
&& error "Encryption of \"$i\" failed."
fi
done
cd - &> /dev/null
fi
[ -n "$COMPRESS" ] \
&& $COMPRESS "$db"[.-]*
done
cd -
### Encryption
if [ -n "$GPGKEYID$GPGPASS" ]; then
echo "### Encryption..."
cd "$backupdir"
for i in *; do
echo "encrypt: $i"
if [ -n "$GPGKEYID" ]; then
gpg -e -r "$GPGKEYID" "$i" \
&& rm "$i"
else
echo "$GPGPASS" \
| gpg -c --batch --passphrase-fd 0 --cipher-algo AES256 "$i" \
&& rm "$i"
}
upload() {
if wants_upload; then
### 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"
fi
done
cd -
fi
if [ ! -n "$FTPTYPE" ]; then
echo "NO FTP UPLOAD CONFIGURED"
else
### FTP: directory permission check
ftpmkdir=$(execftp "mkdir -p $FTPDIR/$date; exit")
if [[ "$ftpmkdir" != *"mkdir OK"* ]]; then
fail "Error: failed to create $FTPDIRnoslash/$date on ftp"
fi
### FTP: delete old backups
echo "### Delete old backups on FTP..."
ftpfiles=$(execftp "cd $FTPDIR; 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 $FTPNUMBACKUPS ]; do
ftpfilesdelete+=(${ftpfiles[0]})
ftpfiles=("${ftpfiles[@]:1}")
done
# delete on ftp
[ ${#ftpfilesdelete[@]} -ge 1 ] \
&& ftpfilesdelete=${ftpfilesdelete[@]} \
&& execftp "cd $FTPDIR; rm -r $ftpfilesdelete; exit"
### FTP: upload
echo "### Upload to FTP..."
execftp "cd $FTPDIR; mirror -R $backupdir; exit"
fi
### 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
ftpfilesdelete+=(${ftpfiles[0]})
ftpfiles=("${ftpfiles[@]:1}")
done
# delete on ftp
[ ${#ftpfilesdelete[@]} -ge 1 ] \
&& ftpfilesdelete=${ftpfilesdelete[@]} \
&& exec_ftp "cd $FTP_DIR; rm -r $ftpfilesdelete; exit"
### FTP: upload
info "Upload to FTP..."
exec_ftp "cd $FTP_DIR; mirror -R $backupdir; exit"
else
warn "No FTP backup configured"
fi
}
check_prerequisites
set_umask
prepare
delete_old_backups
backup
compression
encryption
upload
info "Finished!"
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