-
Notifications
You must be signed in to change notification settings - Fork 9
/
automydumper
executable file
·283 lines (231 loc) · 7.18 KB
/
automydumper
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
#!/bin/bash
export PATH="$PATH:/bin:/usr/bin"
# Defaults
backup_root_dir='/var/backups/automydumper'
backup_dir_format='+%F'
pre_dir='/usr/share/automydumper/pre.d'
post_dir='/usr/share/automydumper/post.d'
compress=1
keep=1
mysql_user='root'
mysql_password=''
mysql_host='localhost'
mysql_socket=
threads=4
mydumper_opts=''
enabled=1
use_savepoints=1
less_locking=1
backup_triggers=1
backup_events=1
backup_routines=1
version="1.3.1"
for cfg in "${HOME}/.automydumper.cfg" /etc/automydumper.cfg; do
# Override defaults if config file is present
if [ -f "${cfg}" ]; then
source "${cfg}"
export AUTOMYDUMPER_CFG_FILE="${cfg}"
break
fi
done
# Overwrite backup when a backup with the same name exists.
overwrite_backup=0
backup_dir_format="${backup_dir_format/ /}"
formatted_date="$(date ${backup_dir_format})"
backup_dir="${backup_root_dir}/${formatted_date}"
export AUTOMYDUMPER_BACKUP_ROOT="${backup_root_dir}"
export AUTOMYDUMPER_BACKUP_DIR="${backup_dir}"
# Set preliminary successful exitcode
export AUTOMYDUMPER_EXIT_CODE=0
export AUTOMYDUMPER_EXIT_MESSAGE=
mydumper_opts="${mydumper_opts} -o ${backup_dir} -v 3 --threads ${threads}"
[ ${compress} -eq 1 ] && mydumper_opts="${mydumper_opts} --compress"
[ ${use_savepoints} -eq 1 ] && mydumper_opts="${mydumper_opts} --use-savepoints"
[ ${less_locking} -eq 1 ] && mydumper_opts="${mydumper_opts} --less-locking"
[ ${backup_triggers} -eq 1 ] && mydumper_opts="${mydumper_opts} --triggers"
[ ${backup_events} -eq 1 ] && mydumper_opts="${mydumper_opts} --events"
[ ${backup_routines} -eq 1 ] && mydumper_opts="${mydumper_opts} --routines"
options=$(getopt -o h -o f --long help --long force -- "$@")
[ $? -eq 0 ] || {
echo "Incorrect options provided"
exit 1
}
eval set -- "$options"
while true; do
case "$1" in
--help|-h)
echo ""
echo "Automydumper ${version}"
echo ""
exit
;;
--force|-f)
overwrite_backup=1
;;
--)
shift
break
;;
esac
shift
done
function mysql_credentials()
{
echo -n "--user=${mysql_user} "
if [ ! -z "${mysql_password}" ]; then
echo -n "--password=${mysql_password} "
fi
if [ ! -z ${mysql_socket} ]; then
echo -n "--socket=${mysql_socket}"
else
echo -n "--host=${mysql_host}"
fi
}
function check_binaries()
{
for binary in "$@"; do
if ! which "${binary}" > /dev/null; then
handle_error "${binary} not installed"
fi
done
}
function show_mydumper_version()
{
echo "Note: Using $(mydumper --version | grep -i mydumper)"
}
function check_mysql_connection()
{
if ! mysql $(mysql_credentials) -e 'select VERSION()' > /dev/null; then
handle_error 'Wrong MySQL credentials or hostname/socket'
fi
}
function cleanup_backups()
{
[ ${AUTOMYDUMPER_EXIT_CODE} -gt 0 ] && return
if [ ${keep} -eq 0 ]; then
echo -e "Cleanup of old backups disabled because of keep=0\n"
return
fi
while [ "$(find "${backup_root_dir}" -type f -name "metadata" | wc -l)" -gt "${keep}" ]; do
oldest=$(find "${backup_root_dir}" -type f -name "metadata" -printf '%Cs %h\n' | sort | head -n 1 | awk '{ print $2}')
echo "Deleting ${oldest}"
rm -rf "${oldest}"
done
echo ""
}
function handle_error()
{
export AUTOMYDUMPER_EXIT_CODE=1
export AUTOMYDUMPER_EXIT_MESSAGE="${1}"
}
function run_commands()
{
command_dir=${1}
# Only run if command dir exists
if [ ! -d ${command_dir} ]; then
echo "Note: ${command_dir} does not exist, not searching for scripts to execute."
return
fi
for cmd in $(find ${1} -maxdepth 1 -type f -executable); do
if [ "${AUTOMYDUMPER_EXIT_CODE}" -eq 0 ]; then
# Only run when the exit code is > 0 when tag below is found
grep automydumper:run:on-error-only ${cmd} &> /dev/null && return
echo "Note: Executing ${cmd}"
echo "--- begin output ---"
${cmd} || handle_error "Command ${cmd} failed"
echo "--- end output ---"
else
if grep -E "automydumper:run:(on-error-only|always)" ${cmd} &> /dev/null; then
echo "Note: Executing ${cmd}"
echo "--- begin output ---"
${cmd} || handle_error "Command ${cmd} failed"
echo "--- end output ---"
fi
fi
done
}
function overwrite_previous_backup()
{
[ ${AUTOMYDUMPER_EXIT_CODE} -gt 0 ] && return
if [ ${overwrite_backup} -eq 0 ]; then
if [ -f "${backup_dir}/metadata" ]; then
echo ""
echo "Backup already exists, doing nothing."
echo "Running automydumper with the '-f' or '--force' option will overwrite the previously taken backup."
echo ""
show_footer
exit 0
elif [ -f "${backup_dir}/metadata.partial" ]; then
echo "Note: Deleting previous partial backup."
fi
else
echo "Note: if a backup with the same name exists it will be forcefully removed"
fi
find "${backup_dir}" -mindepth 1 \( ! -iname "automydumper.log" \) -delete
# Remove broken latest symlink if backup it's pointing to is no longer there.
[ ! -e "${backup_root_dir}/latest" ] && rm -f "${backup_root_dir}/latest"
}
function symlink_latest()
{
rm -f "${backup_root_dir}/latest"
ln -sfr "${backup_dir}" "${backup_root_dir}/latest"
}
function run_mydumper()
{
[ ${AUTOMYDUMPER_EXIT_CODE} -gt 0 ] && return
mydumper_opts="${mydumper_opts} $(mysql_credentials)"
if mydumper ${mydumper_opts}; then
symlink_latest
else
handle_error "Mydumper could not complete backup"
fi
}
function show_header()
{
echo -e "\nAutomydumper version ${version}\n"
echo "Started at `date`"
echo ""
[ -z ${AUTOMYDUMPER_CFG_FILE} ] || echo "Note: Using ${AUTOMYDUMPER_CFG_FILE} to override defaults."
}
function show_footer()
{
if [ ${AUTOMYDUMPER_EXIT_CODE} -gt 0 ]; then
echo ""
echo "Critical: ${AUTOMYDUMPER_EXIT_MESSAGE}. Quitting."
else
echo "Finished at `date`"
fi
}
function validate_date_format()
{
# Make sure only valid chars are there
if ! echo ${formatted_date} | grep -Eq '^[a-zA-Z0-9_:-]+$' &> /dev/null; then
show_header
echo "Critical: date as set in backup_dir_format parameter can only contain numbers, letters, '-', ':' or '_'."
exit 1
fi
}
# Stop the script when it's disabled by the user.
if [ $enabled -eq 0 ]; then
echo "Automydumper is disabled. Enable by removing enabled=0. Quitting without action."
exit 0
fi
trap "{ echo '!! Script interrupted.'; handle_error 'Backup interrupted'; }" INT
validate_date_format
# Make sure backup directory exists
mkdir -p "${backup_dir}"
# Remove the log before we restart the logging when we're overwriting the backup.
[ ${overwrite_backup} -eq 1 ] && rm -f "${backup_dir}/automydumper.log"
exec > >(tee -ia "${backup_dir}/automydumper.log")
exec 2>&1
show_header
check_binaries mysql mydumper
show_mydumper_version
check_mysql_connection
overwrite_previous_backup
run_commands ${pre_dir}
run_mydumper
run_commands ${post_dir}
cleanup_backups
show_footer
exit ${AUTOMYDUMPER_EXIT_CODE}