Lösung: Automatisches Backup: fullbackup_install

Hier ist die Musterlösung zu Aufgabe: Automatisches Backup: fullbackup_install.

Das Skript hat vor dem Installieren den Namen fullbackup_install, uns installiert sich selbst, wenn es mit diesem Namen aufgerufen wird.

Der erhoffte Lernerfolg dieser Musterlösung:

#!/bin/sh
#
#####################################################################
#
# Time-stamp: "29.09.02 15:52 fullbackup_install klaus@wachtler.de"
#
#####################################################################
#
# /etc/backup/fullbackup
# /etc/backup/append       -> /etc/backup/fullbackup
# /etc/backup/delete       -> /etc/backup/fullbackup
# /etc/backup/du           -> /etc/backup/fullbackup
# /etc/backup/incrbackup   -> /etc/backup/fullbackup
# /etc/backup/incrrestore  -> /etc/backup/fullbackup
# /etc/backup/list         -> /etc/backup/fullbackup
# /etc/backup/rewind       -> /etc/backup/fullbackup
#
# fullbackup macht ein volles Backup aller Verzeichnisse (ab /),
# die in $ZUSICHERN aufgeführt sind.
# Datum und Uhrzeit (vor der Sicherung)
# werden in /etc/backup/lastfull und
# /etc/backup/lastincr festgehalten.
# Nachfolgende inkrementelle Sicherungen können sich also auf
# /etc/backup/lastincr beziehen, und diese dann
# aktualisieren.
#
# /etc/backup/lastincr und /etc/backup/lastfull
# werden vor der Sicherung als
# /etc/backup/lastincr.tmp und /etc/backup/lastfull.tmp
# angelegt, und erst bei Erfolg umbenannt.
#
#
# Wenn der Name, mit dem das Skript aufgerufen wird, auf
# "incrbackup" endet, dann wird nur ein inkrementelles
# Backup durchgeführt.
# Wenn das Skript also als "/etc/backup/fullbackup"
# gespeichert ist, und man mit
# "cd /etc/backup/; ln -s fullbackup incrbackup"
# einen Link darauf anlegt, dann wird -wenn
# /etc/backup/incrbackup aufgerufen wird- nur
# ein inkrementelles Backup durchgeführt.
#
# In diesem Fall verhält sich das Skript etwas anders:
#
# - Die Meldungen lauten etwas anders
#
# - Es wird nicht die Merkerdatei "$MERKERFULL"
#   aktualisiert, sondern nur "$MERKERINCR".
#
# - Das Band wird vor der Sicherung ans Ende gespult
#
# - für die Sicherung wird nicht $TAPE, sondern $NTAPE verwendet.
#   Dadurch kann für die inkrementellen Sicherungen ein Band
#   durchgehend im Laufwerk bleiben (wenn $NTAPE nicht automatisch
#   an den Anfang gespult wird). Alle inkrementellen Sicherungen
#   kommen dann hintereinander auf ein Band, bis ein Schreibfehler
#   auftritt. Erst dann muß von Hand das Band gewechselt werden.
#
# - es werden nicht alle Dateien gesichert, sondern
#   nur diejenigen, welche seit dem Anlegen von
#   "$MERKERINCR" modifiziert wurden
#
#
# Endet der Skriptname auf "restore", dann wird das Band an den
# Anfang gespult, und solange von /dev/ntape tar-Archive gelesen,
# bis ein Fehler auftritt.
# Dazu kann man wieder einen symbolischen Link verwenden:
# "cd /etc/backup/; ln -s fullbackup incrrestore"
#
#
# Endet der Skriptname auf "rewind", dann wird das Band an den
# Anfang gespult.
#
#
# Endet der Skriptname auf "list", dann wird der Bandinhalt
# gelistet, und das Band an das Ende der Daten gespult.
#
#
# Endet der Skriptname auf "append", dann wird das Band an das
# Ende der Daten gespult.
#
#
# Endet der Skriptname auf "delete", dann wird das Band gelöscht.
#
#
# Endet der Skriptname auf "du", dann wird festgestellt, wieviel
# Speicherplatz auf dem Band für eine Vollsicherung benötigt wird.
#
#
# Vorgesehene Verwendung:
#
# 0) mit ./fullbackup_install wird das Skript installiert und
#    die Links werden angelegt
#
# 1) gelegentlich wird ein ausreichend großes Band eingelegt,
#    und manuell eine Vollsicherung gestartet (mit
#    "/etc/backup/fullbackup")
#
# 2) Ein weiteres Band für inkrementelle Sicherungen verbleibt
#    im Laufwerk.
#    Über den cron-Dämon wird beispielsweise jede
#    Nacht eine inkrementelle Sicherung angeworfen (mit
#    "/etc/backup/incrbackup").
#    Beispieleintrag für /etc/crontab:
#      # automatisches inkrementelles Backup:
#      0 4 * * *     root  /etc/backup/incrbackup
#    Damit wird jeden morgen um 4:00 ein inkrementelles Backup
#    gestartet.
#    Wenn das Band (für die inkrementellen Sicherungen) voll ist,
#    muß man entweder:
#    a) ein neues Band einlegen, und eine Vollsicherung starten
#       (mit /etc/backup/fullbackup),
#       danach ein leeres Band für die inkrementellen Sicherungen
#       (ggf. mit /etc/backup/delete löschen) im
#       Laufwerk liegen lassen.
#       Damit beginnt der Zyklus von vorne.
#    oder:
#    b) Die letzte Vollsicherung behalten, die Kassette mit den
#       bisherigen ersten inkrementelle Sicherungen als solche
#       kennzeichnen,
#       und eine weitere Kassette für die kommenden inkrementellen
#       Sicherungen ggf. löschen und im Laufwerk lassen.
#
# Zum Restaurieren aller Daten geht man in ein Verzeichnis mit
# reichlich Platz und macht folgendes:
# 1) Kassette mit der Vollsicherung einlegen
# 2) /etc/backup/incrrestore
# 3) Nacheinander für alle Kassetten mit den inkrementellen
#    Sicherungen (in der richtigen Reihenfolge!)
#    a) Kassette einlegen
#    b) /etc/backup/incrrestore
# 4) Wenn man die letzte Kassette jetzt wieder für die nächsten
#    inkrementellen Sicherungen verwenden will:
#    a) diese Kassette einlegen
#    b) an das Ende der Daten spulen (inzwischen überflüssig):
#       /etc/backup/append
#
# Alternativ kann man (wenn man nur eine Datei bzw. wenige wieder
# restaurieren möchte) anhand der Inhaltsverzeichnisse aller Bänder
# (abgelegt in /home/dir/tape*.dir.gz) nach den neuesten Sicherungen
# der Datei(en) suchen, und von Hand mit tar entpacken.
#
#####################################################################
#
# Änderungen:
#
# 31.04.2000 kw   - Selbstinstallierend
#                 - Vor einer inkrementellen Sicherung wird das
#                   Band automatisch ans Ende gespult
#                   (falls der Rechner neu geboootet hat, oder
#                   jemand das Band aus dem Laufwerk genommen hatte,
#                   dann mußte man bisher daran denken, das Band
#                   ans Ende zu spulen, um nicht schon bestehende
#                   Sicherungen am Anfang des Bandes zu
#                   überschreiben.
#                   Das geschieht jetzt automatisch vor jeder
#                   inkrementellen Sicherung.).
#                   Folge: Will man auf einem bereits beschriebenen
#                   Band mit inkrementellen Sicherungen neu beginnen,
#                   dann muß das Band vorher gelöscht werden, sonst
#                   würde die erste Sicherung ja am Ende angefügt
#                   werden (falls da überhaupt Platz ist).
#                 - Zum Löschen des Bandes gibt es dafür jetzt
#                   das Kommando /etc/backup/delete.
#                 - Weitere neue Kommandos:
#                   /etc/backup/append: spult das Band ans Ende
#                   /etc/backup/rewind: spult das Band an den Anfang
#                   /etc/backup/list:   
#
# 02.05.2000 kw   Nach der vollen Sicherung bleibt das Band am Ende
#                 stehen.
#                 Es wird nur noch $NTAPE verwendet, $TAPE ist
#                 überflüssig geworden.
#
#
# 18.05.2001 kw   Bei der Installation wird das Verzeichnis für
#                 die Inhaltsverzeichnisse angelegt
#
#####################################################################
#
# Einstellbare Variablen:
# Liste der zu sichernden Verzeichnisse (ab /, anzugeben ohne
# führenden Schrägstrich, mehrere Verzeichnisse getrennt mit
# Leerzeichen).
# Beispiel:
#  ZUSICHERN="home root var/spool/mail etc usr/local"
#
# (ZUSICHERN wird nur gesetzt, wenn es nicht schon beim Aufruf des
# Skripts gesetzt ist) 
ZUSICHERN=${ZUSICHERN-"home root var/spool/mail etc usr/local"}

# zu verwendendes Laufwerk:
# Band wird NICHT an den Anfang gespult!
NTAPE=/dev/ntape

# Pfad für die Inhaltsverzeichnisse aller Bänder:
VERZEICHNIS_FUER_INHALTSVERZEICHNIS=/home/dir

# Benutzer und Gruppe, auf die das Inhaltsverzeichnis gesetzt werden
# soll (mit anderen Worten: wer darf die Inhaltsverzeichnisse
# sehen?):
DIRUSR=root
DIRGRP=users

# Merkerdateien für Datum der letzten vollen/inkr. Sicherung:
MERKERFULL=/etc/backup/lastfull
MERKERINCR=/etc/backup/lastincr

# Protokolldatei:
LOGFILE=/etc/backup/backup.log

# Verzeichnis für dieses Skript und die Links:
INSTALLDIR=/etc/backup

#
#####################################################################


STARTSTRING=`date +"%Y%m%d_%H%M"`

if [ `echo $0|grep '.*install$'` ]
then

    echo "Installation von $INSTALLDIR/fullbackup"
    if [ `whoami` != "root" ]
    then
        echo "Fehler: Installation nur als root möglich!"
        exit 1
    fi

    # evtl. alten Müll wegwerfen:
    rm -f $INSTALLDIR/append
    rm -f $INSTALLDIR/delete
    rm -f $INSTALLDIR/du
    rm -f $INSTALLDIR/incrbackup
    rm -f $INSTALLDIR/incrrestore
    rm -f $INSTALLDIR/list
    rm -f $INSTALLDIR/rewind

    # Verzeichnis anlegen:
    mkdir -m 700 -p $INSTALLDIR 2>/dev/null
    echo Verzeichnis $INSTALLDIR angelegt

    # Verzeichnis für Inhaltsverzeichnisse anlegen:
    mkdir -m 700 -p $VERZEICHNIS_FUER_INHALTSVERZEICHNIS 2>/dev/null
    echo Verzeichnis $VERZEICHNIS_FUER_INHALTSVERZEICHNIS angelegt


    # Das Skript selbst dahin kopieren:
    cp $0 $INSTALLDIR/fullbackup
    chown root:root $INSTALLDIR/fullbackup
    chmod 500 $INSTALLDIR/fullbackup

    # Und weitere Links darauf anlegen:
    cd $INSTALLDIR
    ln -s fullbackup append
    echo "link angelegt: $INSTALLDIR/append"
    ln -s fullbackup delete
    echo "link angelegt: $INSTALLDIR/delete"
    ln -s fullbackup du
    echo "link angelegt: $INSTALLDIR/du"
    ln -s fullbackup incrbackup
    echo "link angelegt: $INSTALLDIR/incrbackup"
    ln -s fullbackup incrrestore
    echo "link angelegt: $INSTALLDIR/incrrestore"
    ln -s fullbackup list
    echo "link angelegt: $INSTALLDIR/list"
    ln -s fullbackup rewind       
    echo "link angelegt: $INSTALLDIR/rewind"

    true
    exit

fi

if [ `echo $0|grep '.*du$'` ]
then

    echo "Ermitteln des Platzbedarfs..."

    ( cd /; du -c  $ZUSICHERN )

    true
    exit

fi

if [ `echo $0|grep '.*restore$'` ]
then

    echo "Zurückspulen des Bandes..."
    $INSTALLDIR/rewind

    echo "Entpacken aller Archive von $NTAPE ins aktuelle"
    echo "Verzeichnis,"
    echo "bis ein Fehler auftritt..."

    true
    erg=$?
    while [ $erg == "0"  ]
    do
               tar xvf $NTAPE 2>/dev/null
               erg=$?
               if [ $erg == "0" ]
               then
                       echo 
                       echo "  #####  Sicherungssatz gefunden  #####"
                       echo 
               else
                       echo 
                       echo "Ende der Sicherungen?"
                       echo "Das Band steht am Ende der Daten."
               fi
    done
    
    echo "Ende des Zurückladens vom Band."
    exit

fi


if [ `echo $0|grep '.*delete$'` ]
then

    echo "Löschen des Bandes..."
    mt -f $NTAPE erase
    echo "Fertig!"

    exit

fi
if [ `echo $0|grep '.*rewind$'` ]
then

    echo "Zurückspulen des Bandes..."
    mt -f $NTAPE rewind

    echo "Ende des Zurückspulens."

    exit

fi


if [ `echo $0|grep '.*list$'` ]
then

    echo "Zurückspulen des Bandes..."
    $INSTALLDIR/rewind

    echo "Listen aller Archive von $NTAPE,"
    echo " bis ein Fehler auftritt..."

    true
    erg=$?
    while [ $erg == "0"  ]
    do
               tar tvf $NTAPE 2>/dev/null
               erg=$?
               if [ $erg == "0" ]
               then
                       echo 
                       echo "  #####  Sicherungssatz gefunden  #####"
                       echo 
               else
                       echo 
                       echo "Ende der Sicherungen?"
                       echo "Das Band steht am Ende der Daten."
               fi
    done
    
    echo "Ende des Inhaltsverzeichnisses vom Band."

    exit

fi


if [ `echo $0|grep '.*append$'` ]
then

    echo "Spulen des Bandes ans Ende..."
    mt -f $NTAPE eom
    echo "fertig!"

    exit

fi


if [ `echo $0|grep '.*incrbackup$'` ]
then

        # Programmname endet auf "incrbackup", also nur
        # inkrementelles Backup:
        incrbackup="y"
        unset fullbackup
        TEXT="INKREMENTELLES BACKUP"
        text="Inkrementelles Backup"
        NAME=tape.$STARTSTRING.incr

        mt -f $NTAPE eom

else

        # Programmname endet NICHT auf "incrbackup", also
        # volles Backup:
        unset incrbackup
        fullbackup="y"
        TEXT="VOLLBACKUP"
        text="Vollbackup"
        NAME=tape.$STARTSTRING

        mt -f $NTAPE rewind

fi

DIRFILE=$NAME.dir


cd /


# die Merkerdateien erstmal provisorisch anlegen
# (mit Datum/Uhrzeit vom Backupstart):
echo $STARTSTRING >$MERKERINCR.tmp
if [ $fullbackup ]
then

        echo $STARTSTRING >$MERKERFULL.tmp

fi


echo ""  >>$LOGFILE
echo "------------------------------------------"  >>$LOGFILE
echo ""  >>$LOGFILE

echo $text" " `date +"%A %d.%m.%Y %H:%M"`   >>$LOGFILE
echo "(Rechner: " `uname -a` ")"  >>$LOGFILE

echo ""  >>$LOGFILE

if [ $fullbackup ]
then

        # Volles Backup
        tar cvf $NTAPE                                           \
                $ZUSICHERN                                       \
                -V "$NAME"                                       \
                >$DIRFILE  2>>$LOGFILE

else

        # Inkrementelles Backup
        find $ZUSICHERN -newer $MERKERINCR -and -type f -print0 |\
        tar cvf $NTAPE -V $NAME --null -T /dev/stdin             \
        >$DIRFILE 2>>$LOGFILE

fi


if [ $? != "0" ]
then

        # tar meldet einen Fehler

        echo "ABBRUCH! ("`date +"%d.%m.%Y %H:%M"`")"  >>$LOGFILE
        echo ""  >>$LOGFILE

        rm -f $MERKERINCR.tmp
        if [ $fullbackup ]
        then
                rm -f $MERKERFULL.tmp
        fi

        mail -s "$TEXT $STARTSTRING gescheitert!" root <<-EOF
        $0: $text ($STARTSTRING) gescheitert.
        Genaueres steht in $LOGFILE.
        Ende: `date +"%d.%m.%Y %H:%M"`
        EOF

else
        # tar scheint geklappt zu haben.
        # Dann kann man jetzt die Merker für das letzte Backup
        # (etc/backup/lastincr, $MERKERFULL) endgültig
        # anlegen und das Inhaltsverzeichnis komprimieren:

        gzip -9 $DIRFILE
        mv $DIRFILE.gz $VERZEICHNIS_FUER_INHALTSVERZEICHNIS
        chmod 640 $VERZEICHNIS_FUER_INHALTSVERZEICHNIS/$DIRFILE.gz
        chown $DIRUSR:$DIRGRP                                      \
              $VERZEICHNIS_FUER_INHALTSVERZEICHNIS/$DIRFILE.gz
        echo "Inhaltsverzeichnis steht in " \
        $VERZEICHNIS_FUER_INHALTSVERZEICHNIS/$DIRFILE.gz  >>$LOGFILE

        mv $MERKERINCR.tmp $MERKERINCR
        if [ $fullbackup ]
        then
                mv $MERKERFULL.tmp $MERKERFULL
        fi

        echo "ok, fertig ("`date +"%d.%m.%Y %H:%M"`")"  >>$LOGFILE
        echo ""  >>$LOGFILE

        mail -s "$text $STARTSTRING erfolgreich!" root <<-EOF
        $0: $text ($STARTSTRING) erfolgreich.
        Inhaltsverzeichnis steht in\
 $VERZEICHNIS_FUER_INHALTSVERZEICHNIS/$DIRFILE.gz
        Ende: `date +"%d.%m.%Y %H:%M"`
        EOF

fi

# Ende.



AnyWare@Wachtler.de