-
Notifications
You must be signed in to change notification settings - Fork 3
/
mysql-backup.sh
executable file
·160 lines (130 loc) · 6.07 KB
/
mysql-backup.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#!/bin/bash
# Author: Jason Barnett <[email protected]>
export MYSQL_BACKUP_VERSION=1.0
############
## README ##
############
##
## Assumptions this script makes:
## ------------------------------
## -The script itself is run by root
## -root's home is /root
## -MySQL Server version is >= 5.1.2 (That's when the whole --routines switch was added to mysqldump)
## -crontab is configured to email you, help can be found here:
## http://www.cyberciti.biz/faq/linux-unix-crontab-change-mailto-settings/
##
## How to use this script:
## -----------------------
## Simply run this script as is once and it should ask all the right questions and place them in an easy
## to reference config file so it never needs to ask again.
##
## I suggest setting up a cronjob with this script once you've confirmed it's running as expected
## and then putting it in your crontab, e.g.:
##
## 0 2 * * * /path/to/mysql-backup.sh > /dev/null
##
## The reason behind my suggestion is that most people have (or sould have) cron setup so that it only
## emails them when there is any output (both stdout or stderr) from the script/command/etc... I've
## written this script to output to stderr when you need to be notified by email about a problem, e.g.
## it's unable to grab a full list of databases, or it can't authenticate, etc... All of the stdout output
## can be safely ignored. In order for this to work properly though, it requires cron daemon to be configured
## properly so you can receive email from it when things go awry.
##
###########
## Functions ##
###############
. "$( dirname "${BASH_SOURCE[0]}" )/master_functions.sh"
function update_config {
local config_property config_value
config_property=$(echo $1 | awk -F= '{print $1}')
config_value=$(echo $1 | awk -F= '{print $2}')
[[ ! -d ${HOME}/.config/mysql-backup ]] && mkdir -p ${HOME}/.config/mysql-backup
chmod 0700 ${HOME}/.config/mysql-backup
[[ ! -e ${HOME}/.config/mysql-backup/config ]] && touch ${HOME}/.config/mysql-backup/config
chmod 0600 ${HOME}/.config/mysql-backup/config
sed -i "/^${config_property}=/d" ${HOME}/.config/mysql-backup/config
echo "${config_property}=${config_value}" >> ${HOME}/.config/mysql-backup/config
}
function get_mysql_credentials {
MYSQL_USER=$(ask_question "MySQL Username")
[[ -z $MYSQL_USER ]] && exit 1
MYSQL_HOST=$(ask_question "MySQL Host")
MYSQL_PASS=$(ask_question "MySQL Password")
[[ -n ${MYSQL_USER} && -n ${MYSQL_HOST} && -n ${MYSQL_PASS} ]] || {
fail_msg "You have not specified a MySQL Username, Host and/or Password"
}
check_mysql_credentials
update_config "MYSQL_USER=${MYSQL_USER}"
update_config "MYSQL_HOST=${MYSQL_HOST}"
update_config "MYSQL_PASS=${MYSQL_PASS}"
}
function check_mysql_credentials {
temp_file=$(mktemp /tmp/.mysql-backup.XXXXXX)
local good_credentials=
mysql -u${MYSQL_USER} -h${MYSQL_HOST} -p${MYSQL_PASS} \
-BNe 'show databases;' &> ${temp_file} && good_credentials=true
if [[ -z $good_credentials ]];then
fail_msg "You have a bad MySQL Username, Host and/or Password"
fi
rm -f ${temp_file}
}
function ask_about_routines {
ROUTINES=$(ask_yes_no "Dump stored routines?")
update_config "ROUTINES=${ROUTINES}"
}
function get_backup_destination {
BACKUP_DEST=$(ask_question "Choose a backup destination, absolute path only")
while [[ $(echo ${BACKUP_DEST} | grep -E '^((\/[a-zA-Z0-9]+(_[a-zA-Z0-9]+)*(\-[a-zA-Z0-9]+)*)+)$') == "" ]];do
BACKUP_DEST=$(ask_question "I said absolute path only...")
done
update_config "BACKUP_DEST=${BACKUP_DEST}"
}
## MAIN SCRIPT ##
#################
# Check if mysql server even exists on the machine and exit if it's not.
[[ -x /usr/bin/mysqld_safe ]] || { echo "MySQL-Server is not installed on this machine."; exit 0; }
# Set HOME and load config (We set HOME here because most likely we're running from the crontab and HOME isn't set)
HOME=/root
[[ -e ${HOME}/.config/mysql-backup/config ]] && . ${HOME}/.config/mysql-backup/config
# Check for MySQL credentials
if [[ -n ${MYSQL_USER} && -n ${MYSQL_HOST} && -n ${MYSQL_PASS} ]]; then
check_mysql_credentials
else
get_mysql_credentials
fi
# Should we dump routines?
[[ -n ${ROUTINES} && (${ROUTINES} == "true" || ${ROUTINES} == "false") ]] || ask_about_routines
[[ ${ROUTINES} == "true" ]] && ROUTINES='--routines' || ROUTINES=
# Check for backup destination, create it if it doesn't exist, and set the correct permissions
[[ -n ${BACKUP_DEST} ]] || get_backup_destination
[[ ! -d ${BACKUP_DEST} ]] && mkdir -p ${BACKUP_DEST}
chown root:root -R ${BACKUP_DEST}
chmod 0700 ${BACKUP_DEST}
# Locate gzip binary and try to use pigz (multi-threaded gzip), or fallback and use gzip
GZIP=$(command -v pigz 2> /dev/null)
[[ -z ${GZIP} ]] && { GZIP=$(command -v gzip 2> /dev/null); msg "INFO: You don't have pigz installed, using gzip instead."; msg " This is not a big deal, pigz simply speeds up the backup process."; }
# Locate mysqldump binary
MYSQLDUMP=$(command -v mysqldump 2> /dev/null)
[[ -z ${MYSQLDUMP} ]] && fail_msg "Unable to locate \"mysqldump\". Make sure it's in your \$PATH."
# Get a list of all databases
DBs="$(mysql -u${MYSQL_USER} -h${MYSQL_HOST} -p${MYSQL_PASS} -BNe 'show databases;' | grep -E -v '^(information_schema|performance_schema)$')"
mysql_status=$?
[[ $mysql_status != "0" ]] && fail_msg "There was an issue grabbing a complete list of databases to backup."
backup_failed=
for db in ${DBs};do
FILE="${BACKUP_DEST}/${db}.sql.gz"
[ -f ${FILE}.2 ] && rm -f ${FILE}.2
[ -f ${FILE}.1 ] && mv ${FILE}.1 ${FILE}.2
[ -f ${FILE}.0 ] && mv ${FILE}.0 ${FILE}.1
[ -f ${FILE} ] && mv ${FILE} ${FILE}.0
echo -n "Backing up $db... "
if ${MYSQLDUMP} -u${MYSQL_USER} -h${MYSQL_HOST} -p${MYSQL_PASS} $ROUTINES -B ${db} | $GZIP -9 > ${FILE};
then
msg Success!
else
err_msg Failed!
backup_failed=true
failed_dbs="$db $failed_dbs"
fi
done
[[ $backup_failed == "true" ]] && fail_msg "There was an issue backing up the following databases: ${failed_dbs}"