-
Notifications
You must be signed in to change notification settings - Fork 14
/
pull_binlog.sh
executable file
·200 lines (160 loc) · 5.61 KB
/
pull_binlog.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
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
#!/bin/bash
#
# Backup binlog files using mysqlbinlog 5.6
# Daniel Guzman Burgos <[email protected]>
#
clear
set -o pipefail
# Initial values
lockFile="/var/lock/binlog-pull.lock"
errorFile="/var/log/mysql/pull-binlogs.err"
logFile="/var/log/mysql/pull-binlogs.log"
retention=30 # Retention in days
mysqlUser=root
mysqlPort=3306
mysqlPassword=""
remoteHost=localhost
binPrefix="mysql-bin"
backupPath="/root/backups"
respawn=3 # How many attempts to restart the mysqlbinlog process try
email="root@localhost"
# Function definitions
function sendAlert () {
if [ -e "$errorFile" ]
then
alertMsg=$(cat $errorFile)
echo -e "${alertMsg}" | mailx -s "[$HOSTNAME] ALERT binlog backups" "${email}"
fi
}
function destructor () {
sendAlert
local latest=$(ls -1 $backupPath | grep $binPrefix | tail -1)
rm -f $lockFile $errorFile
}
# Setting TRAP in order to capture SIG and cleanup things
trap destructor EXIT INT TERM
function verifyExecution () {
local exitCode="$1"
local mustDie=${3-:"false"}
if [ $exitCode -ne "0" ]
then
msg="[ERROR] Failed execution. ${2}"
echo "$msg" >> ${errorFile}
if [ "$mustDie" == "true" ]; then
exit 1
else
return 1
fi
fi
return 0
}
function setLockFile () {
pidmbl=$(pidof mysqlbinlog)
if [[ -e "$lockFile" || ! -z "$pidmbl" ]]; then
trap - EXIT INT TERM
verifyExecution "1" "Script already running. $lockFile exists or mysqlbinlog is already running. $pidmbl"
sendAlert
rm -f "$errorFile"
exit 2
else
touch "$lockFile"
fi
}
function logInfo (){
echo "[$(date +%y%m%d-%H:%M:%S)] $1" >> $logFile
}
function getBinlogSize () {
binlogSize=$(mysql -u${mysqlUser} --password=${mysqlPassword} -h${remoteHost} --port=${mysqlPort} -N -e"show variables like 'max_binlog_size'" 2> /dev/null | awk '{print $2}' 2>&1)
verifyExecution "$?" "Error getting max_binlog_size $out"
if [ -z "$binlogSize" ]; then
binlogSize=1024
logInfo "[Warning] Cannot get max_binlog_size value, instead 1024 Bytes used"
return
fi
logInfo "[OK] max_binlog_size obtained: $binlogSize"
}
function verifyMysqlbinlog () {
which mysqlbinlog &> /dev/null
verifyExecution "$?" "Cannot find mysqlbinlog tool" true
logInfo "[OK] Found 'mysqlbinlog' utility"
haveRaw=$(mysqlbinlog --help | grep "\--raw")
if [ -z "$haveRaw" ]
then
verifyExecution "1" "Incorrect mysqlbinlog version. Needs 5.6 version with --raw parameter" true
fi
logInfo "[OK] Verified mysqlbinlog utility version"
}
function findFirstBinlog () {
local first=$(mysql -u${mysqlUser} --password=${mysqlPassword} -h${remoteHost} --port=${mysqlPort} -N -e"show binary logs" 2> /dev/null | head -n1 | awk '{print $1}')
echo $first
}
function findLatestBinlog () {
pushd $backupPath &> /dev/null
verifyExecution "$?" "Backup path $backupPath does not exists" true
local latest=$(ls -1 | grep $binPrefix | tail -1)
msg="[OK] Found latest backup binlog: $latest"
if [ -z "$latest" ]; then
latest=$(findFirstBinlog)
msg="[Warning] No binlog file founded on backup directory (${backupPath}). Using instead $latest as first file (obtained from SHOW BINARY LOGS)"
fi
logInfo "$msg"
popd &>/dev/null
latest=${latest%%.gz}
echo "$latest"
}
function pullBinlogs () {
firstBinlogFile=$(findLatestBinlog)
pushd $backupPath &> /dev/null
out=$(mysqlbinlog --raw --read-from-remote-server --stop-never --verify-binlog-checksum --user=${mysqlUser} --password=${mysqlPassword} --host=${remoteHost} --port=${mysqlPort} --stop-never-slave-server-id=54060 $firstBinlogFile 2>&1) &
verifyExecution "$?" "Error while launching mysqlbinlog utility. $out"
pidMysqlbinlog=$(pidof mysqlbinlog)
logInfo "[OK] Launched mysqlbinlog utility. Backup running: mysqlbinlog --raw --read-from-remote-server --stop-never --verify-binlog-checksum --user=${mysqlUser} --password=XXXXX --host=${remoteHost} --port=${mysqlPort} --stop-never-slave-server-id=54060 $firstBinlogFile"
popd &>/dev/null
}
function rotateBackups () {
out=$(find $backupPath -type f -name "${binPrefix}*" -mtime +${retention} -print | xargs /bin/rm 2>&1)
es=$?
if [ "$es" -ne 123 ]; then
verifyExecution "$es" "Error while removing old backups. $out" true
fi
}
function compressBinlogs () {
pushd $backupPath &> /dev/null
local now=$(date +%s)
local skipFirst=1
for i in $(ls -1t | grep $binPrefix | grep -v ".gz"); do
if [ $skipFirst -eq 1 ]; then
skipFirst=0
continue;
fi
local created=$(stat -c %Y $i)
local diff=$(($now-$created))
local size=$(du -b $i | awk '{print $1}')
if [[ $size -ge $binlogSize || $diff -gt 300 ]]; then
out=$(gzip $i 2>&1)
verifyExecution "$?" "Error compressing binlog file ${i}. $out" true
fi
done
popd &>/dev/null
}
function verifyAllRunning () {
local tryThisTimes=$(echo $respawn)
while true; do
if [ ! -d /proc/$pidMysqlbinlog ]; then
logInfo "[ERROR] mysqlbinlog stopped. Attempting a restart .... "
pullBinlogs
tryThisTimes=$(($tryThisTimes-1))
if [ $tryThisTimes -eq 0 ]; then
verifyExecution "1" "Error while restarting mysqlbinlog utility after $respawn attempts. Terminating the script" true
fi
fi
compressBinlogs
rotateBackups
sleep 30;
done
}
setLockFile
verifyMysqlbinlog
getBinlogSize
pullBinlogs
verifyAllRunning