Backup eines LVM-Systems erstellen mit Hilfe von Snaphots

Aus Bluelupo's Wiki
Wechseln zu: Navigation, Suche

Bashscript run_lvmsnap.sh

  1 #!/bin/bash
  2 #
  3 ########## Variablendefinitionen ##########
  4 OF_DIR="/mnt/backup/diskdump/`date '+%Y-%m-%d-%H%M'`"
  5 TIMESTAMP=`date '+%Y%m%d_%H%M'`
  6 LOGFILE_TIMESTAMP=`date '+%d.%m.%Y'`
  7 SYSMOUNT1="/"
  8 SYSMOUNT2="/opt"
  9 SYSMOUNT3="/usr"
 10 SYSMOUNT4="/var"
 11 SYSMOUNT5="/home"
 12 SYSMOUNT6="/boot"
 13 INDEX_CTRL="0"
 14 LOGFILE="/var/log/lvmsnap.log"
 15 MAILRECIPIENT="michael@localhost"
 16 LOCKPATH="/var/lock"
 17 LOCKFILE=`basename $0.lck`
 18 METADATA="metadata.txt"
 19 MD5SUMFILE="all_md5sums.txt"
 20 ERRFILE="errorlog.txt"
 21 ########## Funktionsdefinitionen ##########
 22 usage()
 23 {
 24    echo "Dieses Script sichert einzelne, systemrelevante oder alle LV's mit Hilfe eines Snapshot-Verfahren (LVM)."
 25    echo "Die temporaer erstellten Snapshots werden dann per Diskdump (dd) 1:1 gesichert. Die Nicht-LVM-Partition (/boot)"
 26    echo "wird ebenfalls per Diskdump gesichert. Alle relevanten Metadaten die bei einer evtl. Wiederherstellung des Systems"
 27    echo "nuetzlich sind, werden bei jeder Sicherung mitprotokoliert. Eine Komprimierung der Backups findet nicht statt,"
 28    echo "deshalb bitte auf den zu Verfuegung stehenden Speicherplatz achten."
 29    echo ""
 30    echo "Syntax: $0 [-h | -a | -s | -r | -u | -b | -n <Mount_Point_LV> | -m]"
 31    echo ""
 32    echo " -h (help):         diese Hilfeseite"
 33    echo " -a (all):          von allen LVs in allen VG's Snapshotbackups erstellen"
 34    echo " -s (system):       nur von System-LVs (root,boot,home,opt,usr,var) Snapshotbackups erstellen, sowie Bootpartition sichern"
 35    echo " -r (rootonly):     nur von Root-LV (/) Snapshotbackup erstellen"
 36    echo " -u (userdataonly): nur von Home-LV (/home) Snapshotbackup erstellen"
 37    echo " -b (bootonly):     nur von Bootpartition (/boot) die eine Nicht-LVM-Partition ist einen Diskdumpbackup erstellen"
 38    echo " -n (name):         benutzerspezifischen Snapshotbackup erstellen"
 39    echo " -m (MBR):          Master-Boot-Record (MBR) sichern"
 40    echo ""
 41    echo "Bitte beachten, die Optionen sind exklusiv, d.h. sie schliessen sich gegenseitig aus und somit nur einzelnen verwendet werden."
 42    echo ""
 43    exit 1
 44 }
 45 
 46 debug_printarray()
 47 {
 48    echo "-----------------Debuging Ausgabe--------------------"
 49    for I in ${ARRAY_LV[@]}
 50       do
 51       echo $I
 52    done
 53    echo "-----------------Debuging Ausgabe--------------------"
 54    echo ""
 55 }
 56 
 57 print_message()
 58 {
 59    MISSINGARGUMENT="Bei der Option -$OPTION wurde ein falscher Mountpoint angegeben"
 60    NOTAVAILIBLEOPT="Option $2 ist nicht erlaubt und wird ignoriert"
 61    LOCKMESG="Ein anderer Prozess von $0 blockiert die Ausfuehrung - Abbruch des Scripts"
 62 
 63    if [ "$1" = "MISSINGARGUMENT" ]
 64       then
 65       echo $MISSINGARGUMENT
 66    elif [ "$1" = "NOTAVAILIBLEOPT" ]
 67       then
 68       echo $NOTAVAILIBLEOPT
 69    elif [ "$1" = "LOCKED" ]
 70       then
 71       echo $LOCKMESG 
 72    fi
 73    
 74 }
 75 
 76 create_LVlist()
 77 {
 78    for ROW in `/sbin/lvdisplay -c |cut -d":" -f1,8`
 79       do
 80       TMP=${ROW##*/}
 81       LVNAME=`echo $TMP | cut -d":" -f1`
 82       MOUNTPOINT=`mount | egrep "\-$LVNAME on " | cut -d" " -f3`
 83 
 84       if [ "$1" = "$MOUNTPOINT" ]
 85          then
 86          ARRAY_LV[$INDEX_LV]=$ROW:$LVNAME:$MOUNTPOINT
 87          INDEX_CTRL=`expr $INDEX_CTRL + 1`
 88       elif [ "$1" = "all" ]
 89          then
 90          ARRAY_LV[$INDEX_LV]=$ROW:$LVNAME:$MOUNTPOINT
 91          INDEX_CTRL=`expr $INDEX_CTRL + 1`
 92       elif [ "$1" = "systemonly" ]
 93          then
 94          case "$MOUNTPOINT" in
 95             $SYSMOUNT1|$SYSMOUNT2|$SYSMOUNT3|$SYSMOUNT4|$SYSMOUNT5|$SYSMOUNT6)
 96             ARRAY_LV[$INDEX_LV]=$ROW:$LVNAME:$MOUNTPOINT
 97             INDEX_CTRL=`expr $INDEX_CTRL + 1`
 98             ;;
 99          esac
100       fi
101       INDEX_LV=`expr $INDEX_LV + 1`
102    done
103 }
104 
105 do_snapshot()
106 {
107    for I in ${ARRAY_LV[@]}
108       do
109       if [ ! -d "$OF_DIR" ]
110          then
111          mkdir $OF_DIR >> $LOGFILE 2>&1
112          if [ $? -eq 0 ]
113             then
114             echo " Create directory succesfully: $OF_DIR" >> $LOGFILE 2>&1 
115             echo "" >> $LOGFILE 2>&1 
116          fi
117       fi
118 
119       if [ -e $OF_DIR/$ERRFILE ]
120          then
121          echo -n "  --> Size of error file: `ls -ld $OF_DIR/$ERRFILE | cut -d' ' -f5` Byte" >> $LOGFILE 2>&1
122          echo "" >> $LOGFILE 2>&1
123          echo "  --> Location of error file://$OF_DIR/$ERRFILE" >> $LOGFILE 2>&1
124          echo "" >> $LOGFILE 2>&1
125       fi
126 
127       LVNAME_LONG=`echo $I | cut -d":" -f1`
128       LECOUNTER=`echo $I | cut -d":" -f2`
129       LVNAME_SHORT=`echo $I | cut -d":" -f3`
130       VGPATH=`dirname $LVNAME_LONG`
131       /sbin/lvcreate -l$LECOUNTER -s -n SNAPSHOT_$LVNAME_SHORT $LVNAME_LONG 1>> $LOGFILE 2>> $OF_DIR/$ERRFILE
132       dd if=$VGPATH/SNAPSHOT_$LVNAME_SHORT of=$OF_DIR/$LVNAME_SHORT-$TIMESTAMP.dd >> $LOGFILE 2>&1
133       /sbin/lvremove -f $VGPATH/SNAPSHOT_$LVNAME_SHORT 1>> $LOGFILE 2>> $OF_DIR/$ERRFILE
134    done
135 }
136 
137 do_boot_dd()
138 {
139    BOOTDEVPATH=`mount | grep -w '/boot' | cut -d" " -f1`
140    BOOTDEV=`basename $BOOTDEVPATH`
141    BOOTNAME=$(basename `mount | grep -w '/boot' | cut -d" " -f3`)
142    if [ ! -d "$OF_DIR" ]
143       then
144       mkdir $OF_DIR >> $LOGFILE 2>&1   
145       if [ $? -eq 0 ]
146          then
147          echo "create directory succesfully: $OF_DIR" >> $LOGFILE 2>&1 
148       fi
149    fi   
150    dd if=$BOOTDEVPATH of=$OF_DIR/$BOOTDEV$BOOTNAME-$TIMESTAMP.dd >> $LOGFILE 2>&1
151    echo "$BOOTDEVPATH saved" >> $LOGFILE 2>&1
152 }
153 
154 do_mailsend()
155 {
156    MAILSUBJECT="[SNAPSHOT]: Backup (-$OPTION) vom $LOGFILE_TIMESTAMP durchgefuehrt"
157    sed -n "/\[Log started: $LOGFILE_START_TIMESTAMP\]/,/\[Log ended: $LOGFILE_END_TIMESTAMP\]/p" $LOGFILE | mailx -s "$MAILSUBJECT" $MAILRECIPIENT
158 }
159 
160 do_save_mbr()
161 {
162    MBRDEVPATH="/dev/sda"
163    MBRDEV=$(basename $MBRDEVPATH)
164    MBRNAME="MBR"
165    echo "" >> $LOGFILE 2>&1
166    echo " Try to save $MBRNAME" >> $LOGFILE 2>&1
167    dd if=$MBRDEVPATH of=$OF_DIR/$MBRDEV$MBRNAME-$TIMESTAMP.dd bs=512 count=1 >> $LOGFILE 2>&1
168    echo -n "  --> Size of error file: `ls -ld $OF_DIR/$ERRFILE | cut -d' ' -f5` Byte" >> $LOGFILE 2>&1
169    echo "" >> $LOGFILE 2>&1
170    echo "  --> Location of error file://$OF_DIR/$ERRFILE" >> $LOGFILE 2>&1
171    echo " $MBRNAME from disk $MBRDEVPATH saved" >> $LOGFILE 2>&1
172 }
173 
174 create_logentry()
175 {
176    if [ "$1" = "start" ]
177       then
178       LOGFILE_START_TIMESTAMP=`date '+%Y-%m-%d %H:%M:%S'`
179       echo "[Log started: $LOGFILE_START_TIMESTAMP]" >> $LOGFILE
180    elif [ "$1" = "stop" ]
181       then
182       LOGFILE_END_TIMESTAMP=`date '+%Y-%m-%d %H:%M:%S'`
183       echo "[Log ended: $LOGFILE_END_TIMESTAMP]" >> $LOGFILE
184    fi
185 }
186 
187 do_save_metadata()
188 {
189    echo "" >> $LOGFILE 2>&1
190    echo " Begin to save all metadata from `/bin/hostname`" >> $LOGFILE 2>&1
191    echo "  --> All metadata stored in file://$OF_DIR/$METADATA" >> $LOGFILE 2>&1
192    echo "  --> Diskgeometry" >> $LOGFILE 2>&1
193    /sbin/fdisk -l 2>>$OF_DIR/$ERRFILE | egrep -v " doesn't contain a valid partition table" >> $OF_DIR/$METADATA
194    echo "" >> $OF_DIR/$METADATA
195    echo "  --> PVs" >> $LOGFILE 2>&1 
196    /sbin/pvdisplay 2>>$OF_DIR/$ERRFILE | egrep -v " leaked on " >> $OF_DIR/$METADATA
197    echo "" >> $OF_DIR/$METADATA
198    echo "  --> VGs" >> $LOGFILE 2>&1
199    /sbin/vgdisplay 2>>$OF_DIR/$ERRFILE | egrep -v " leaked on " >> $OF_DIR/$METADATA
200    echo "" >> $OF_DIR/$METADATA
201    echo "  --> LVs" >> $LOGFILE 2>&1
202    /sbin/lvdisplay 2>>$OF_DIR/$ERRFILE | egrep -v " leaked on " >> $OF_DIR/$METADATA
203    echo "" >> $OF_DIR/$METADATA
204    echo "  --> Filesystem parameters" >> $LOGFILE 2>&1
205    for FS in `mount | egrep "^/dev" | cut -d" " -f1`
206       do
207       /sbin/tune2fs -l $FS >> $OF_DIR/$METADATA
208       echo "" >> $OF_DIR/$METADATA
209    done
210    echo "  --> Mountpoints" >> $LOGFILE 2>&1
211    /bin/mount >> $OF_DIR/$METADATA
212    echo "" >> $OF_DIR/$METADATA
213    echo "  --> Diskfree" >> $LOGFILE 2>&1
214    /bin/df -k >> $OF_DIR/$METADATA
215    echo "" >> $OF_DIR/$METADATA
216    echo "  --> File type of the image files to determine" >> $LOGFILE 2>&1
217    file $OF_DIR/*.dd >> $OF_DIR/$METADATA 2>&1
218    echo -n "  --> Size of error file: `ls -ld $OF_DIR/$ERRFILE | cut -d' ' -f5` Byte" >> $LOGFILE 2>&1
219    echo "" >> $LOGFILE 2>&1
220    echo "  --> Location of error file: file://$OF_DIR/$ERRFILE" >> $LOGFILE 2>&1
221    echo " All metadata saved from `/bin/hostname`" >> $LOGFILE 2>&1
222 }
223 
224 do_checksum()
225 {
226    echo "" >> $LOGFILE 2>&1
227    echo " Start with creating the md5 sums" >> $LOGFILE 2>&1
228    echo "  --> All Checksums stored in file://$OF_DIR/$MD5SUMFILE" >> $LOGFILE 2>&1
229    for FILE in $OF_DIR/*.dd
230       do
231       echo "  --> Try to create the md5 sum of file `basename $FILE`" >> $LOGFILE 2>&1
232       md5sum $FILE >> $OF_DIR/$MD5SUMFILE
233       RC=$?
234       if [ $RC -eq 0 ]
235          then
236          echo "    --> Could md5-sum without creating errors" >> $LOGFILE 2>&1
237       elif [ $RC -ne 0 ]
238          then
239          echo "    --> An error occurred while creating the md5 sum" >> $LOGFILE 2>&1
240       fi
241    done
242    echo " All md5 sums generated" >> $LOGFILE 2>&1
243    echo "" >> $LOGFILE 2>&1
244    RC=""
245 }
246 
247 do_lock()
248 {
249    if [ "$1" = "on" ]
250       then
251       echo " --> Processing begins now" >> $LOGFILE 2>&1
252       pidof -x $0 > $LOCKPATH/$LOCKFILE
253       echo " Set lock in file $LOCKPATH/$LOCKFILE" >> $LOGFILE 2>&1
254    elif [ "$1" = "off" ]
255       then
256       rm -v $LOCKPATH/$LOCKFILE >> $LOGFILE 2>&1
257       echo " Done, lock file $LOCKPATH/$LOCKFILE removed" >> $LOGFILE 2>&1
258       echo " --> Script run complete" >> $LOGFILE 2>&1
259    fi
260 }
261 
262 do_runtest()
263 {
264    if [ ! -e $LOCKPATH/$LOCKFILE ]
265       then
266       do_lock on
267    else
268       print_message LOCKED
269       echo "No run available (lockfile: $LOCKPATH/$LOCKFILE)" >> $LOGFILE 2>&1
270       create_logentry stop
271       exit 2
272    fi
273 }
274 
275 if [ $# -eq 0 -o $# -gt 2 ]; then
276    usage
277 fi
278 
279 ########## Hauptprogramm ##########
280 while getopts hasrubn:m OPTION; do
281    case $OPTION in
282       h)
283       usage
284       ;;
285       a)
286       create_logentry start
287       do_runtest
288       create_LVlist all
289       do_snapshot
290       do_save_mbr
291       do_save_metadata
292       do_checksum
293       do_lock off
294       create_logentry stop
295       do_mailsend
296       ;;
297       s)
298       create_logentry start
299       do_runtest
300       create_LVlist systemonly
301       do_snapshot
302       do_save_mbr
303       do_save_metadata
304       do_checksum
305       do_lock off
306       create_logentry stop
307       do_mailsend
308       ;;
309       r)
310       create_logentry start
311       do_runtest
312       create_LVlist /
313       do_snapshot
314       do_save_mbr
315       do_save_metadata
316       do_lock off
317       create_logentry stop
318       do_mailsend
319       ;;
320       u)
321       create_logentry start
322       do_runtest
323       create_LVlist /home
324       do_snapshot
325       do_save_metadata
326       do_checksum
327       do_lock off
328       create_logentry stop
329       do_mailsend
330       ;;
331       b)
332       create_logentry start
333       do_runtest
334       do_boot_dd
335       do_save_metadata
336       do_checksum
337       do_lock off
338       create_logentry stop
339       do_mailsend
340       ;;
341       n)
342       create_logentry start
343       do_runtest
344       create_LVlist $OPTARG
345       if [ "$INDEX_CTRL" != "0" ]
346          then
347          do_snapshot
348       elif [ "$INDEX_CTRL" = "0" ]
349          then
350          print_message MISSINGARGUMENT
351       fi
352       do_save_metadata
353       do_checksum
354       do_lock off
355       create_logentry stop
356       do_mailsend
357       ;;
358       m)
359       create_logentry start
360       do_runtest
361       do_save_mbr
362       do_checksum
363       do_lock off
364       create_logentry stop
365       do_mailsend
366       ;;
367       \?)
368       create_logentry start
369       FALSEOPT=$1
370       print_message NOTAVAILIBLEOPT $FALSEOPT
371       do_lock off
372       create_logentry stop
373       read ret
374       exit 3
375       ;;
376    esac
377 done
378 shift `expr $OPTIND - 1`
379 exit 0
380 #EOF