MySQL Database Backup
The script show below can be run on Linux, Solaris and other Unix flavours as daily cron job. It creates a MySQL database dump for every database in a separate file. Older backups are consolidated by recycling the file name so that the hard disk or NFS share isn't filled.
- Daily backupfile named after weekday (e. g.
database.daily_Wednesday.sql). After seven days it will be overwritten. - On the last day in the month the file is named after the month number (e. g.
database.monthly_09.sql). After twelve months it is overwritten. - On 31 december the file is named after the year (e. g.
database.yearly_2013.sql. This file is kept forever.
Program execution as follows:
/usr/local/bin/mysqlbackup.sh dbhost1.example.com:3306 dbhost2.example.com:3306
In der MySQL Datenbank muss ein User mit folgenden Privilegien erstellt werden:
grant show databases,show view,file,select,lock tables \ on *.* to 'backup'@'backuphost.example.com' identified by 'changeme';
Add user and password in the MySQL configuration file .my.cnf in the user home directory.
[client] user=backup password=changeme [mysqldump] max-allowed-packet=2147483648 quote-names=true verbose=true
Here's the bash script:
#!/bin/bash
PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin"
BACKUPDIR="/var/backup/mysql"
CONFIG="/home/user/.my.cnf"
EXCLUDEDB='^(Database|information_schema|performance_schema)$'
MAILFROM="backup@example.com"
MAILTO="user@example.com"
# Simple housekeeping
# Daily backups with week day names
# Monthly backups on the last day of month
# Yearly backups on last day of december
year=$(date "+%Y")
month=$(date "+%m")
monthname=$(date "+%B")
day=$(date "+%d")
dayname=$(date "+%A")
d=28
if (( $year % 4 == 0 )); then d=29; fi
if (( $year % 100 == 0 )); then d=28; fi
if (( $year % 400 == 0 )); then d=29; fi
case "$month:$day" in
01:31) timestamp="monthly_${month}" ;;
02:$d) timestamp="monthly_${month}" ;;
03:31) timestamp="monthly_${month}" ;;
04:30) timestamp="monthly_${month}" ;;
05:31) timestamp="monthly_${month}" ;;
06:30) timestamp="monthly_${month}" ;;
07:31) timestamp="monthly_${month}" ;;
08:31) timestamp="monthly_${month}" ;;
09:30) timestamp="monthly_${month}" ;;
10:31) timestamp="monthly_${month}" ;;
11:30) timestamp="monthly_${month}" ;;
12:31) timestamp="yearly_${year}" ;;
*) timestamp="daily_${dayname}" ;;
esac
for hostport in $@; do
echo ""
echo "*******************************************************************************"
echo "Backing up MySQL on $hostport to $BACKUPDIR"
echo "*******************************************************************************"
echo ""
host=$(echo $hostport | awk -F: '{print $1}')
port=$(echo $hostport | awk -F: '{print $2}')
hostdir="$BACKUPDIR/$hostport"
test -d $hostdir || mkdir -p $hostdir
databases=$(echo "show databases;" \
| mysql --defaults-file="$CONFIG" -h "$host" -P "$port" | grep -Ev "$EXCLUDEDB")
for db in $databases; do
echo -n "Dumping database $db ... "
dbdir="$hostdir/$db"
dumpfile="$dbdir/${db}.${timestamp}.sql"
logfile="$dbdir/${db}.${timestamp}.log"
test -d $dbdir || mkdir -p $dbdir
mysqldump --defaults-file="$CONFIG" --log-error="$logfile" \
-h "$host" -P "$port" "$db" >$dumpfile
retval=$?
chmod 0644 $logfile
chmod 0400 $dumpfile
case $retval in
0) echo "OK" ;;
*) echo "FAILED"
( echo "From: $MAILFROM"
echo "To: $MAILTO"
echo "Subject: Error backing up MySQL database $db on $hostport"
echo ""
echo "The command"
echo "mysqldump --defaults-file=$CONFIG --log-error=$logfile -h $host -P $port $db"
echo "returned value: $retval"
echo ""
echo "Error log: $logfile"
echo "$(cat $logfile)"
echo "."
) | sendmail -t
;;
esac
done
done