mysql: Put most of the code into a function.
[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 function make_backup() {
55    vsname="$1"
56    if [ -n "$vsname" ]; then
57       vroot="$VROOTDIR/$vsname"
58       vexec="$VSERVER $vsname exec"
59    else
60       vroot=""
61       vexec=""
62    fi
63
64    interpolated=`interpolate "$backupdir" "$vsname"`
65
66    # create backup dirs, $vroot will be empty if no vsname was specified
67    # and we will instead proceed to operate on the host
68    [ -d $vroot$interpolated ] || mkdir -p $vroot$interpolated
69    [ -d $vroot$interpolated ] || fatal "Backup directory '$vroot$backupdir'"
70
71    hotdir="$interpolated/hotcopy"
72    dumpdir="$interpolated/sqldump"
73
74    [ "$sqldump" == "no" -o -d $vroot$dumpdir ] || mkdir -p $vroot$dumpdir
75    [ "$hotcopy" == "no" -o -d $vroot$hotdir ] || mkdir -p $vroot$hotdir
76
77    #######################################################################
78    ## AUTHENTICATION
79
80    #
81    # one of three authentication methods:
82    # 1. setting the user, so that /home/user/.my.cnf is used.
83    # 2. specifying the user and password in the handler config,
84    #    which generates a temporary .my.cnf in /root/.my.cnf
85    # 3. specify the config file with --defaults-extra-file
86    #    (this option DOESN'T WORK WITH MYSQLHOTCOPY)
87    #
88
89    # create .my.cnf
90    # only if dbusername and dbpassword specified.
91    # we create a tmp file because we don't want to
92    # specify the password on the command line.
93
94    defaultsfile=""
95
96    if [ "$dbusername" != "" -a "$dbpassword" != "" ]
97    then
98       vhome=`$vexec getent passwd "root" | @AWK@ -F: '{print $6}'`
99       home=$vroot$vhome
100
101       [ -d $home ] || fatal "Can't find root's home directory ($home)."
102
103       mycnf="$home/.my.cnf"
104
105       if [ -f $mycnf ]
106       then
107          # rename temporarily
108          tmpcnf="$home/my.cnf.disable"
109          debug "mv $mycnf $tmpcnf"
110          mv $mycnf $tmpcnf
111       fi
112
113       oldmask=`umask`
114       umask 077
115       cat > $mycnf <<EOF
116    # auto generated backupninja mysql conf
117    [mysql]
118    host=$dbhost
119    user=$dbusername
120    password="$dbpassword"
121
122    [mysqldump]
123    host=$dbhost
124    user=$dbusername
125    password="$dbpassword"
126
127    [mysqlhotcopy]
128    host=$dbhost
129    user=$dbusername
130    password="$dbpassword"
131 EOF
132       umask $oldmask
133       defaultsfile="--defaults-extra-file=$vhome/.my.cnf"
134    fi
135
136    # if a user is not set, use $configfile, otherwise use $mycnf
137    if [ "$user" == "" ]; then
138       user=root;
139       defaultsfile="--defaults-extra-file=$configfile"
140    else
141       userset=true;
142       if [ $usevserver = yes ]
143       then
144          vuserhome=`$vexec getent passwd "$user" | @AWK@ -F: '{print $6}'`
145          if [ $? -eq 2 ]
146          then
147             fatal "User $user not found in /etc/passwd"
148          fi
149          userhome="$vroot$vuserhome"
150       fi
151
152       debug "User home set to: $userhome"
153       [ -f $userhome/.my.cnf ] || fatal "Can't find config file in $userhome/.my.cnf"
154       defaultsfile="--defaults-extra-file=$vuserhome/.my.cnf"
155       debug "using $defaultsfile"
156    fi
157
158    #######################################################################
159    ## HOT COPY
160
161    if [ "$hotcopy" == "yes" ]
162    then
163       info "Initializing hotcopy method"
164       if [ "$databases" == "all" ]
165       then
166          info "dbhost: $dbhost"
167          execstr="$vexec $MYSQLHOTCOPY -h $dbhost --quiet --allowold --regexp /.\*/./.\*/ $hotdir"
168
169          debug "su $user -c \"$execstr\""
170          if [ ! $test ]
171          then
172             output=`su $user -c "$execstr" 2>&1`
173             code=$?
174             if [ "$code" == "0" ]
175             then
176                     debug $output
177                     info "Successfully finished hotcopy of all mysql databases"
178             else
179                     warning $output
180                     warning "Failed to hotcopy all mysql databases"
181             fi
182          fi
183       else
184          for db in $databases
185          do
186             execstr="$vexec $MYSQLHOTCOPY -h $dbhost --allowold $db $hotdir"
187
188             debug 'su $user -c \"$execstr\"'
189             if [ ! $test ]
190             then
191                output=`su $user -c "$execstr" 2>&1`
192                code=$?
193                if [ "$code" == "0" ]
194                then
195                   debug $output
196                   info "Successfully finished hotcopy of mysql database $db"
197                else
198                   warning $output
199                   warning "Failed to hotcopy mysql database $db"
200                fi
201             fi
202          done
203       fi
204    fi
205
206    ##########################################################################
207    ## SQL DUMP
208
209    if [ "$sqldump" == "yes" ]
210    then
211        info "Initializing SQL dump method"
212        if [ "$databases" == "all" ]
213        then
214            debug "$vexec su $user -c \"$MYSQL $defaultsfile -N -B -e 'show databases'\" | sed 's/|//g;/\+----/d'"
215            # -N removes the column title and -B should remove the ASCII table borders, but doesn't always so we use sed to make sure.
216            databases=`$vexec su $user -c "$MYSQL $defaultsfile -N -B -e 'show databases'" | sed 's/|//g;/\+----/d'`
217            if [ $? -ne 0 ]
218            then
219                fatal "Authentication problem, maybe user/password is wrong or mysqld is not running?"
220            fi
221        fi
222
223            for db in $databases
224            do
225               DUMP_BASE="$MYSQLDUMP $defaultsfile $sqldumpoptions"
226
227               # Dumping structure and data
228               DUMP="$DUMP_BASE $ignore $db"
229
230               # If requested, dump only the table structure for this database
231               if echo "$nodata" | grep -E '(^|[[:space:]])'"$db\." >/dev/null
232               then
233                  # Get the structure of the tables, without data
234                  DUMP_STRUCT="$DUMP_BASE --no-data $db"
235                  for qualified_table in $nodata
236                  do
237                     table=$( expr match "$qualified_table" "$db\.\([^\w]*\)" )
238                     DUMP_STRUCT="$DUMP_STRUCT $table"
239                  done
240                  DUMP="( $DUMP; $DUMP_STRUCT )"
241               fi
242                    # Test to make sure mysqld is running, if it is not sqldump will not work
243                    $vexec su $user -c "$MYSQLADMIN $defaultsfile ping"
244                    if [ $? -ne 0 ]; then
245                       fatal "Either you have an authentication problem, or mysqld doesn't appear to be running!"
246                    fi
247                    if [ "$compress" == "yes" ]; then
248                       execstr="$vexec $DUMP | $GZIP > $vroot$dumpdir/${db}.sql.gz"
249                    else
250                       execstr="$vexec $DUMP -r $vroot$dumpdir/${db}.sql"
251                    fi
252
253                    debug "su $user -c \"$execstr\""
254                    if [ ! $test ]
255                    then
256                            output=`su $user -c "$execstr" 2>&1`
257                            code=$?
258                            if [ "$code" == "0" ]
259                            then
260                                    debug $output
261                                    info "Successfully finished dump of mysql database $db"
262                            else
263                                    warning $output
264                                    warning "Failed to dump mysql databases $db"
265                            fi
266                    fi
267            done
268    fi
269
270    # clean up tmp config file
271    if [ "$dbusername" != "" -a "$dbpassword" != "" ]
272    then
273            ## clean up tmp config file
274            debug "rm $mycnf"
275            rm $mycnf
276            if [ -f "$tmpcnf" ]
277            then
278                    debug "mv $tmpcnf $mycnf"
279                    mv $tmpcnf $mycnf
280            fi
281    fi
282 }
283
284 if [ $usevserver = yes ]; then
285    make_backup "$vsname"
286 else
287    make_backup ""
288 fi
289
290 return 0