Ticket #1081: sqlbackup.sh

File sqlbackup.sh, 16.5 kB (added by anonyme, 1 year ago)

sqlbackup.sh scripts

Line 
1 #!/bin/bash
2
3 # $Id: sqlbackup.sh,v 2.0 2006/10/17 17:32:05 mistur Exp $
4 # ----------------------------------------------------------------------
5 # AlternC - Web Hosting System
6 # Copyright (C) 2002 by the AlternC Development Team.
7 # http://alternc.org/
8 # ----------------------------------------------------------------------
9 # Based on:
10 # Valentin Lacambre's web hosting softwares: http://altern.org/
11 # ----------------------------------------------------------------------
12 # LICENSE
13 #
14 # This program is free software; you can redistribute it and/or
15 # modify it under the terms of the GNU General Public License (GPL)
16 # as published by the Free Software Foundation; either version 2
17 # of the License, or (at your option) any later version.
18 #
19 # This program is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 # GNU General Public License for more details.
23 #
24 # To read the license please visit http://www.gnu.org/copyleft/gpl.html
25 # ----------------------------------------------------------------------
26 # Original Author of file: Benjamin Sonntag - 2003-03-23
27 # Purpose of file: MySQL Database backup shell script for AlternC
28 # ----------------------------------------------------------------------
29 # Changed by Yoann Moulin : 2006-10-16
30 # * Adding an other possibilty for name of the backup files which
31 #   avoid renaming old backup files (name rotation methode)
32 #   this methode include the date of the backup day in the name of the
33 #   file
34 #   Usefull for person who use rsync, rsnapshot, etc... this methode
35 #   avoid to sync old files which just has been rename but seem diff
36 #   for sync script
37 set -e
38
39 # Get mysql user and password :
40 . /etc/alternc/local.sh
41 . /etc/alternc/sqlbackup.conf
42
43 # get the date of the day
44 DATE=`date +"%Y%m%d"`
45
46 # echo function, used for output wrapping when run in daemon
47 # mode.
48 # usage: print [option] <message>
49 #   without option, print <message> in any case on the stdout 
50 #
51 # options :
52 #   error : print <message> in any case and indicate that an error message
53 #   debug : print <message> if debug mode is active
54 #   info  : print <message> if verbose mode is active
55 #
56 # notes :
57 #   if backup running in daemon mode, printing in log file if an otpion
58 #   is gived to the function
59 print() {
60    
61     # if a log level is given to the print function
62     # 'error', 'info' or 'debug'
63     log_level=""
64     if [ "$1" == "error" ] || [ "$1" == "info" ] || [ "$1" == "debug" ];
65     then
66         # read it and remove it for arg list
67         log_level="$1"
68         shift
69     fi
70
71     # if
72     #  - No log level is specified
73     #  - Log level equal to 'error'
74     #    => print in any case on stdout
75     #    => add to log file as well if $DAEMON set to 'ON'
76     #  - Log level equal to 'debug' and $DEBUG is set to on
77     #  - Log level equal to 'info' and $VERBOSE set to 'ON'
78     #     => print on log file if $DAEMON set to 'ON', on stdout if not
79     if [ -z "$log_level" ] ||
80     [ "$log_level" == "error" ] ||
81     [ "$DEBUG" == "ON"  -a  "$log_level" == "debug" ]  ||
82     [ "$log_level" == "info" -a  "$VERBOSE" == "ON" ] ;
83     then
84         if [ "$DAEMON" == "ON" ] ; then
85             # function without option must be print on stdout in anycase
86             # even if print in the log file
87             if [ -z "$log_level" ] || [ "$log_level" == "error" ];
88             then
89                 echo "$EXEC_CMD $log_level: $*"
90             fi
91             echo "`date +"%b %d %T"` `hostname` $EXEC_CMD $log_level: $*" >> $F_LOG
92         else
93             if [ -z "$log_level" ];
94             then
95                 echo "$*"
96             else
97                 echo "$log_level: $*"
98             fi
99         fi
100     fi
101    
102 }
103
104 error() {
105     print "error" $*
106 }
107
108 info() {
109     print "info" $*
110 }
111 debug() {
112     print "debug" $*
113 }
114
115 function dobck() {
116     local ext
117     local i
118     local old_ifs
119    
120     # mysql -B uses tab as a separator between fields, so we have to mess
121     # with IFS in order to get the correct behaviour
122     old_ifs="$IFS"
123     IFS="       "
124     # read parameter given by mysql
125     while read login pass db count compressed target_dir; do
126        
127         debug "read $login \$pass $db $count $compressed $target_dir"
128         # restore $IFS after read parameter
129         IFS="$old_ifs"
130
131         # by default : DOBAKCUP set to yes
132         DO_BACKUP="YES"
133        
134         if [ "$compressed" -eq 1 ]; then
135             ext=".gz"
136         else
137             ext=""
138         fi
139
140         # if $TYPE_NAME_BACKUP is set to "rotate" classical rotation files methode will be used
141         # use incrementale number in the name of files where the highest number indicate
142         # the oldest files
143         # if the rotate type is not set or set to date, the name of the export file will contain the date
144         # of the backup on won't be rotate by the classic rotate number
145         # usefull if you're using rsync or rsnapshop or everything base on rsync to avoir to copy
146         # rotate files which just change name
147         #
148         # ------------------------------------------------------------------ #
149         # the variable TYPE_NAME_BACKUP must be set in /etc/alternc/local.sh #
150         # ------------------------------------------------------------------ #
151         if [ $TYPE_NAME_BACKUP == "rotate" ]; then
152            
153             i="$count"
154            
155             # rotate all backup
156             while [ $i -gt 1 ] ; do
157              
158               next_i=$(($i - 1))
159            
160               if [ -e "${target_dir}/${db}.sql.${next_i}${ext}" ]; then
161                 mv -f "${target_dir}/${db}.sql.${next_i}${ext}" \
162                       "${target_dir}/${db}.sql.${i}${ext}" 2>/dev/null
163               fi
164               i=$next_i # loop should end here
165             done
166            
167             # move most recently backup with a rotate file name
168             if [ -e "${target_dir}/${db}.sql${ext}" ]; then
169               mv -f "${target_dir}/${db}.sql${ext}" \
170                     "${target_dir}/${db}.sql.${i}${ext}" 2>/dev/null
171             fi
172
173             name_backup_file="${db}"
174          else   
175             # ---------------
176             # default methode   
177             # ---------------
178             # calcul the mtime parameter for find
179             # $count is the number of backup to keep
180             # daily  : if we are keeping X backup, deleting the file which has the mtime at X + 1 days
181             # weekly : if we are keeping X backup, deleting the file which has the mtime at (X + 1) * 7 day
182             # echo "last2del=( $count + 1 ) * $coef "
183             #
184             last2del=$(( ( $count + 1 ) * $coef ))
185            
186             # find the oldest backup file need to be delete
187             # find ${target_dir}     : in the target_dir
188             # -name \"${db}.*sql.*\" : All files like <db_name>.*sql.*
189             # -maxdepth 0            : only in the target dir (on not in the subdirectory)
190             # -mtime $last2del       : files with the exact mtime set to $last2del
191             #                          daily  : ( number of backup to keep + 1 ) days
192             #                          weekly : ( number of backup to keep + 1 ) * 7 days
193             # -exec rm -f {} \;      : remove all files found
194             #
195             debug "find ${target_dir} -name \"${db}.*sql${ext}\" -maxdepth 1 -mtime +$last2del -exec rm -f {} \; -ls"
196             find ${target_dir} -name "${db}.*sql${ext}" -maxdepth 1 -mtime +${last2del} -exec rm -f {} \; -ls
197            
198             # set the name of the backup file with the date of the day
199             name_backup_file="${db}.${DATE}"
200            
201        fi
202      
203        # if the backup exite and ALLOW_OVERWRITE_BACKUP is set to NO, cancel backup
204        if [ -f "${target_dir}/${name_backup_file}.sql${ext}" ] && [ "$ALLOW_OVERWRITE_BACKUP"  == "no" ] ; then
205            
206            info "sqlbackup.sh: ${target_dir}/${name_backup_file}.sql${ext}: already exist"
207            info "              => no backup done as specify in allow-overwrite = $ALLOW_OVERWRITE_BACKUP"
208            DO_BACKUP="NO"
209
210         # if the backup exite and ALLOW_OVERWRITE_BACKUP is set to RENAME, add 
211         elif [ -f "${target_dir}/${name_backup_file}.sql${ext}" ] && [ "$ALLOW_OVERWRITE_BACKUP"  == "rename" ] ; then
212
213            info "sqlbackup.sh: ${target_dir}/${name_backup_file}.sql${ext}: already exist"
214            info "              => renaming the new file as specify in allow-overwrite = $ALLOW_OVERWRITE_BACKUP"
215            hours=`date +"%H%M"`
216            name_backup_file="${name_backup_file}.${hours}"
217
218         # if the backup exite and ALLOW_OVERWRITE_BACKUP is set OVERWRITE, add 
219         elif [ -f "${target_dir}/${name_backup_file}.sql${ext}" ] && [ "$ALLOW_OVERWRITE_BACKUP"  == "overwrite" ] ; then
220
221            info "sqlbackup.sh: ${target_dir}/${name_backup_file}.sql${ext}: already exist"
222            info "              => overwrite file as specify in allow-overwrite = $ALLOW_OVERWRITE_BACKUP"
223            
224        fi
225
226        ###
227        # mysqldump Option :
228        # --add-drop-table  : Add a 'drop table' before each create.
229        #                     usefull if you want to override the database without delete table before
230        #                     this is need to used restore from the alternc interface
231        # --allow-keywords  : Allow creation of column names that are keywords.
232        #                     
233        # --quote-names     : Quote table and column names with `
234        #                     Usefull if you have space in table or column names
235        # --force           : Continue even if we get an sql-error.
236        #                     To avoid end of script during backup script execution
237        #                     Allow script to backup other database if one of the have an error
238        # --quick           : Don't buffer query, dump directly to stdout.
239        #                     optimisation option
240        # --all             : Include all MySQL specific create options.
241        #                     Permit keep information like type or comment
242        # --extended-insert : Allows utilization of the new, much faster INSERT syntax.
243        #                     optimization option
244        # (--add-locks       : Add locks around insert statements.)
245        # (--lock-tables     : Lock all tables for read.)
246        #                      those 2 options avoid insert during dump which can create an unconsistent
247        #                      state of the database backup
248        #                      remove because lock is allow for alternc user
249        if [ "$compressed" -eq 1 ] && [ "$DO_BACKUP" == "YES" ]; then
250            debug "msqldump -h\"$MYSQL_HOST\" -u\"$login\" -p\"XXXX\" \"$db\" --add-drop-table --allow-keywords -Q -f -q -a -e \ "
251            debug "         | gzip -c > \"${target_dir}/${name_backup_file}.sql${ext}\""
252
253            mysqldump -h"$MYSQL_HOST" -u"$login" -p"$pass" "$db" \
254                         --add-drop-table \
255                         --allow-keywords \
256                         --quote-names \
257                         --force \
258                         --quick \
259                         --all \
260                         --extended-insert \
261                         | gzip -c > "${target_dir}/${name_backup_file}.sql${ext}"
262
263        elif [ "$DO_BACKUP" == "YES" ] ; then
264             debug "mysqldump -h\"$MYSQL_HOST\" -u\"$login\" -p\"XXXX\" \"$db\" --add-drop-table --allow-keywords -Q -f -q -a -e \ "
265             debug "          > \"${target_dir}/${name_backup_file}.sql\""
266            
267             mysqldump -h"$MYSQL_HOST" -u"$login" -p"$pass" "$db" \
268                         --add-drop-table \
269                         --allow-keywords \
270                         --quote-names \
271                         --force \
272                         --quick \
273                         --all \
274                         --extended-insert \
275                         > "${target_dir}/${name_backup_file}.sql"
276         fi
277
278         IFS="   "
279     done
280     IFS="$old_ifs"
281 }
282
283 # read_parameters gets all command-line arguments and analyzes them
284 #
285 # return:
286 read_parameters() {
287
288     # for all parameter give to the script
289     while [ "$1" != "" ] ; do
290         case "$1" in
291             -h|--help) usage; exit ;;
292             -v|--verbose) VERBOSE="ON" ;;
293             -d|--debug) DEBUG="ON" ;;
294             -t|--type) shift; TYPE="$1";;
295             -n|--name-methode) shift; TYPE_NAME_BACKUP="$1";;
296             -a|--allow-ovewrite) shift; ALLOW_OVERWRITE_BACKUP="$1" ;;
297             *)
298                 error "invalide option -- $1"
299                 error "Try \`sqlbackup.sh --help' for more information."
300                 exit ;;
301         esac
302         # in case of no argument give to an option
303         # shift execute an exit if already empty
304         # add test to avoid this at least to print error message
305         [ "$1" != "" ] && shift   
306     done
307
308     debug "TYPE = $TYPE"
309     debug "TYPE_NAME_BACKUP = $TYPE_NAME_BACKUP"
310     debug "ALLOW_OVERWRITE_BACKUP = $ALLOW_OVERWRITE_BACKUP"
311    
312
313     # check options
314     if [ "$TYPE" == "daily" ]; then
315         # Daily :
316         mode=2
317         coef=1
318     elif [ "$TYPE" == "weekly" ] ; then
319         # Weekly:
320         mode=1
321         coef=7
322     elif [ -n "$TYPE" ] ; then
323         error "missing argument: type"
324         error "Try \`sqlbackup.sh --help' for more information."
325         exit
326     else
327         error "invalide argument: type -- $TYPE"
328         error "Try \`sqlbackup.sh --help' for more information."
329         exit
330     fi
331
332     if ! ( [ -z "$TYPE_NAME_BACKUP" ] ||
333            [ "$TYPE_NAME_BACKUP" == "date" ] ||
334            [ "$TYPE_NAME_BACKUP" == "rotate" ] ) ; then
335         error "invalide argument: name-methode -- $TYPE_NAME_BACKUP"
336         error "Try \`sqlbackup.sh --help' for more information."
337         exit
338      fi
339
340     if ! ( [ -z  "$ALLOW_OVERWRITE_BACKUP" ] ||
341            [ "$ALLOW_OVERWRITE_BACKUP" == "no" ] ||
342            [ "$ALLOW_OVERWRITE_BACKUP" == "rename" ] ||
343            [ "$ALLOW_OVERWRITE_BACKUP" == "overwrite" ] ); then
344         error "invalide argument: allow-ovewrite -- $ALLOW_OVERWRITE_BACKUP"
345         error "Try \`sqlbackup.sh --help' for more information."
346         exit
347      fi
348
349 }
350
351 # a quick intro to the software, displayed when no params found
352 usage() {
353     echo "Usage: sqlbackup.sh [OPTION] -t TYPE
354
355 sqlbackup.sh is a script used by alternc for sql backup
356
357 Mandatory arguments to long options are mandatory for short options too.
358   -v, --verbose                 set verbose mode on
359   -d, --debug                   set debug mode on
360   -n, --name-method  METHOD     set the method type for files' name
361   -a, --allow-override OVERRIDE specify the behaviour if backup files already exist
362   -t, --type TYPE               set backup type
363   -h, --help                    display this help and exit
364
365 the TYPE arguments specify type of backup.  Here are the values:
366
367     daily           Execute a daily backup on all databases set to daily backup
368     weekly          Execute a daily backup on all databases set to weekly backup
369
370 the METHOD argument the type for files' name.  Here are the values:
371
372     date            insert in the backup file's name the date of the backup
373                     (default value)
374     rotate          rename file as file.<number><extension> where <number>
375                     is incremented
376
377 the OVERRIDE argument the behaviour of the script if a backup file already exist.
378 Here are the values:
379
380     no              if a backup file already exist, no backup done
381     rename          if a backup file already exist, add an extension to the new
382                     backup file
383
384     overwrite       if a backup file already exist, overwrite it with the new 
385                     backup"
386
387 }
388 debug begin $@
389 # read all paramter before doing anything before
390 read_parameters $@
391 debug end
392
393 ###
394 # select backup information from the alternc database in the db table
395 # all backup for the specify mode (daily or weekly)
396 # option :
397 #   --batch : Print results with a tab as separator, each row on a new line.
398 #             avoid seperator like "|" which are not usefull in a shell script
399 #             need to set the IFS environment variable to "\t" (tabbulation) for
400 #             the `read' command (indicate field separator by default `read'
401 #             use space)
402 # tail -n '+2' permit to skip the first line (legende line)
403 # execut dobck on all database found by the sql request
404 #
405 # the "<< EOF" mean send data to the command until EOF (end of file)
406 #
407 debug /usr/bin/mysql -h"$MYSQL_HOST" -u"$MYSQL_USER" -p"XXXX" "$MYSQL_DATABASE" -B
408 /usr/bin/mysql -h"$MYSQL_HOST" -u"$MYSQL_USER" -p"$MYSQL_PASS" \
409 "$MYSQL_DATABASE" --batch << EOF | tail -n '+2' | dobck
410 SELECT login, pass, db, bck_history, bck_gzip, bck_dir
411   FROM db
412  WHERE bck_mode=$mode;
413 EOF
414
415 # vim: et sw=4
416