a6cd023ae7b422675c342775d9e3c1f3c4557464
[matthijs/upstream/backupninja.git] / handlers / mysql.in
1 # -*- mode: sh; sh-basic-offset: 3; indent-tabs-mode: nil; -*-
2 #
3 # mysql handler script for backupninja
4 #
5
6 getconf backupdir /var/backups/mysql
7 getconf databases all
8 getconf ignores
9 getconf nodata
10 getconf dbhost localhost
11 getconf hotcopy no
12 getconf sqldump no
13 getconf sqldumpoptions "--lock-tables --complete-insert --add-drop-table --quick --quote-names"
14 getconf compress yes
15 getconf vsname
16
17 # authentication:
18 getconf user
19 getconf dbusername
20 getconf dbpassword
21 getconf configfile /etc/mysql/debian.cnf
22
23
24 # Decide if the handler should operate on a vserver or on the host.
25 # In the former case, check that $vsname exists and is running.
26 local usevserver=no
27 local vroot
28 if [ $vservers_are_available = yes ]; then
29    if [ -n "$vsname" ]; then
30       # does it exist ?
31       if ! vservers_exist "$vsname" ; then
32          fatal "The vserver given in vsname ($vsname) does not exist."
33       fi
34       # is it running ?
35       vservers_running $vsname || fatal "The vserver $vsname is not running."
36       # everything ok
37       info "Using vserver '$vsname'."
38       usevserver=yes
39    else
40       info "No vserver name specified, actions will be performed on the host."
41    fi
42 else
43    [ -z "$vsname" ] || warning 'vservers support disabled in backupninja.conf, vsname configuration line will be ignored'
44 fi
45
46 ## Prepare ignore part of the command
47 ## This only works for mysqldump at the moment
48
49 ignore=''
50 for i in $ignores $nodata; do
51        ignore="$ignore --ignore-table=$i"
52 done
53
54 if [ $usevserver = yes ]; then
55    vroot="$VROOTDIR/$vsname"
56    vexec="$VSERVER $vsname exec"
57 else
58    vroot=""
59    vexec=""
60    vsname=""
61 fi
62
63 interpolated=`interpolate "$backupdir" "$vsname"`
64
65 # create backup dirs, $vroot will be empty if no vsname was specified
66 # and we will instead proceed to operate on the host
67 [ -d $vroot$interpolated ] || mkdir -p $vroot$interpolated
68 [ -d $vroot$interpolated ] || fatal "Backup directory '$vroot$backupdir'"
69
70 hotdir="$interpolated/hotcopy"
71 dumpdir="$interpolated/sqldump"
72
73 [ "$sqldump" == "no" -o -d $vroot$dumpdir ] || mkdir -p $vroot$dumpdir
74 [ "$hotcopy" == "no" -o -d $vroot$hotdir ] || mkdir -p $vroot$hotdir
75
76 #######################################################################
77 ## AUTHENTICATION
78
79 #
80 # one of three authentication methods:
81 # 1. setting the user, so that /home/user/.my.cnf is used.
82 # 2. specifying the user and password in the handler config,
83 #    which generates a temporary .my.cnf in /root/.my.cnf
84 # 3. specify the config file with --defaults-extra-file
85 #    (this option DOESN'T WORK WITH MYSQLHOTCOPY)
86 #
87
88 # create .my.cnf
89 # only if dbusername and dbpassword specified.
90 # we create a tmp file because we don't want to
91 # specify the password on the command line.
92
93 defaultsfile=""
94
95 if [ "$dbusername" != "" -a "$dbpassword" != "" ]
96 then
97     vhome=`$vexec getent passwd "root" | @AWK@ -F: '{print $6}'`
98     home=$vroot$vhome
99
100     [ -d $home ] || fatal "Can't find root's home directory ($home)."
101     
102     mycnf="$home/.my.cnf"
103     
104     if [ -f $mycnf ]
105     then
106         # rename temporarily
107         tmpcnf="$home/my.cnf.disable"
108         debug "mv $mycnf $tmpcnf"
109         mv $mycnf $tmpcnf
110     fi
111     
112     oldmask=`umask`
113     umask 077
114     cat > $mycnf <<EOF
115 # auto generated backupninja mysql conf
116 [mysql]
117 host=$dbhost
118 user=$dbusername
119 password="$dbpassword"
120
121 [mysqldump]
122 host=$dbhost
123 user=$dbusername
124 password="$dbpassword"
125
126 [mysqlhotcopy]
127 host=$dbhost
128 user=$dbusername
129 password="$dbpassword"
130 EOF
131         umask $oldmask
132         defaultsfile="--defaults-extra-file=$vhome/.my.cnf"
133 fi
134
135 # if a user is not set, use $configfile, otherwise use $mycnf
136 if [ "$user" == "" ]; then
137         user=root;
138         defaultsfile="--defaults-extra-file=$configfile"
139 else
140         userset=true;
141         if [ $usevserver = yes ]
142         then
143             vuserhome=`$vexec getent passwd "$user" | @AWK@ -F: '{print $6}'`
144             if [ $? -eq 2 ]
145             then
146                 fatal "User $user not found in /etc/passwd"
147             fi
148             userhome="$vroot$vuserhome"
149         fi
150         
151         debug "User home set to: $userhome"
152         [ -f $userhome/.my.cnf ] || fatal "Can't find config file in $userhome/.my.cnf"
153         defaultsfile="--defaults-extra-file=$vuserhome/.my.cnf"
154         debug "using $defaultsfile"
155 fi
156
157 #######################################################################
158 ## HOT COPY
159
160 if [ "$hotcopy" == "yes" ]
161 then
162     info "Initializing hotcopy method"
163     if [ "$databases" == "all" ]
164     then
165         info "dbhost: $dbhost"
166         execstr="$vexec $MYSQLHOTCOPY -h $dbhost --quiet --allowold --regexp /.\*/./.\*/ $hotdir"
167
168         debug "su $user -c \"$execstr\""
169         if [ ! $test ]
170         then
171                 output=`su $user -c "$execstr" 2>&1`
172                 code=$?
173                 if [ "$code" == "0" ]
174                 then
175                         debug $output
176                         info "Successfully finished hotcopy of all mysql databases"
177                 else
178                         warning $output
179                         warning "Failed to hotcopy all mysql databases"
180                 fi
181         fi
182     else        
183         for db in $databases
184         do
185                 execstr="$vexec $MYSQLHOTCOPY -h $dbhost --allowold $db $hotdir"
186
187                 debug 'su $user -c \"$execstr\"'
188                 if [ ! $test ]
189                 then
190                         output=`su $user -c "$execstr" 2>&1`
191                         code=$?
192                         if [ "$code" == "0" ]
193                         then
194                                 debug $output
195                                 info "Successfully finished hotcopy of mysql database $db"
196                         else
197                                 warning $output
198                                 warning "Failed to hotcopy mysql database $db"
199                         fi
200                 fi
201         done
202      fi
203 fi
204
205 ##########################################################################
206 ## SQL DUMP
207
208 if [ "$sqldump" == "yes" ]
209 then
210     info "Initializing SQL dump method"
211     if [ "$databases" == "all" ]
212     then
213         debug "$vexec su $user -c \"$MYSQL $defaultsfile -N -B -e 'show databases'\" | sed 's/|//g;/\+----/d'"
214         # -N removes the column title and -B should remove the ASCII table borders, but doesn't always so we use sed to make sure.
215         databases=`$vexec su $user -c "$MYSQL $defaultsfile -N -B -e 'show databases'" | sed 's/|//g;/\+----/d'`
216         if [ $? -ne 0 ]
217         then
218             fatal "Authentication problem, maybe user/password is wrong or mysqld is not running?"
219         fi
220     fi
221
222         for db in $databases
223         do
224            DUMP_BASE="$MYSQLDUMP $defaultsfile $sqldumpoptions"
225
226            # Dumping structure and data
227            DUMP="$DUMP_BASE $ignore $db"
228
229            # If requested, dump only the table structure for this database
230            if echo "$nodata" | grep -E '(^|[[:space:]])'"$db\." >/dev/null
231            then
232               # Get the structure of the tables, without data
233               DUMP_STRUCT="$DUMP_BASE --no-data $db"
234               for qualified_table in $nodata
235               do
236                  table=$( expr match "$qualified_table" "$db\.\([^\w]*\)" )
237                  DUMP_STRUCT="$DUMP_STRUCT $table"
238               done
239               DUMP="( $DUMP; $DUMP_STRUCT )"
240            fi
241                 # Test to make sure mysqld is running, if it is not sqldump will not work
242                 $vexec su $user -c "$MYSQLADMIN $defaultsfile ping"
243                 if [ $? -ne 0 ]; then
244                    fatal "Either you have an authentication problem, or mysqld doesn't appear to be running!"
245                 fi
246                 if [ "$compress" == "yes" ]; then
247                    execstr="$vexec $DUMP | $GZIP > $vroot$dumpdir/${db}.sql.gz"
248                 else
249                    execstr="$vexec $DUMP -r $vroot$dumpdir/${db}.sql"
250                 fi
251
252                 debug "su $user -c \"$execstr\""
253                 if [ ! $test ]
254                 then
255                         output=`su $user -c "$execstr" 2>&1`
256                         code=$?
257                         if [ "$code" == "0" ]
258                         then
259                                 debug $output
260                                 info "Successfully finished dump of mysql database $db"
261                         else
262                                 warning $output
263                                 warning "Failed to dump mysql databases $db"
264                         fi
265                 fi
266         done
267 fi
268
269 # clean up tmp config file
270 if [ "$dbusername" != "" -a "$dbpassword" != "" ]
271 then
272         ## clean up tmp config file
273         debug "rm $mycnf"
274         rm $mycnf
275         if [ -f "$tmpcnf" ]
276         then
277                 debug "mv $tmpcnf $mycnf"
278                 mv $tmpcnf $mycnf
279         fi
280 fi
281
282 return 0