ubuntuusers.de

backup.sh

Datum:
5. Mai 2012 19:03
Code:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
ls -al

-rwxr-xr-x  1 xbmc xbmc  3103 Mai  5 18:40 bkup321.conf
-rwxr-xr-x  1 xbmc xbmc 10533 Mai  5 18:39 bkup321.sh


xbmc@HTPC:~/hdd2/backup$ cat bkup321.sh
#!/bin/bash
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#                                                                                       #
# = = = = = = = = = = = = = = = = = = RSYNC BACKUP  = = = = = = = = = = = = = = = = = = #
#                                                                                       #
# Author:   JaiBee, http://www.321tux.de                                                #
# Date:     2011-01-02                                                                  #
# Version:  0.98                                                                        #
# License:  Creative Commons "Namensnennung-Nicht-kommerziell-                          #
#           Weitergabe unter gleichen Bedingungen 3.0 Unported "                        #
#           [ http://creativecommons.org/licenses/by-nc-sa/3.0/deed.de ]                #
#                                                                                       #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Dieses Skript sichert / synchronisiert Verzeichnisse mit rsync.
# Dabei können beliebig viele Profile konfiguriert oder die Pfade direkt an das Skript übergeben werden.
# Eine kurze Anleitung kann mit der Option -h aufgerufen werden.
#set -x

# Konfigurationsdatei [Wenn Skript=bkup321.sh Konfig=bkup321.conf]
if [ -f ${0%%.*}.conf ] ; then
   source ${0%%.*}.conf
else
    echo -e "\033[1;41m FEHLER \033[0;1m Die Konfigurationsdatei fehlt.\033[0m (\"${0%%.*}.conf\")"
    exit 1
fi

###################################### FUNKTIONEN #######################################

# Wird in der Konsole angezeigt, wenn eine Option nicht angegeben oder definiert wurde
function func_help(){
        echo -e "Aufruf: \033[1m$0 \033[34m-p\033[0m \033[1;36mARGUMENT\033[0m [\033[1;34m-p\033[0m \033[1;36mARGUMENT\033[0m]"
        echo -e "        \033[1m$0 \033[34m-m\033[0m \033[1;36mQUELLE(n)\033[0m \033[1;36mZIEL\033[0m"
        echo
        echo -e "\033[4merforderlich\033[0m"
        for i in $(seq ${#arg[*]});     do echo -e "  \033[1;34m-p\033[0m \033[1;36m${arg[$i]}\033[0m   Profil \"${title[$i]}\""; done
        echo -e "oder\n  \033[1;34m-a\033[0m    alle Backup-Profile"
        echo -e "oder\n  \033[1;34m-m\033[0m    Verzeichnisse manuell angeben"
        echo
        echo -e "\033[4moptional\033[0m"
        echo -e "  \033[1;34m-s\033[0m  PC nach Beendigung automatisch herunterfahren (benötigt u.U. Root-Rechte)"
        echo -e "  \033[1;34m-d\033[0m \033[1;36mx\033[0m       Alte Backup-Dateien die älter als x Tage sind löschen"
        echo -e "  \033[1;34m-h\033[0m  Hilfe anzeigen"
        echo
        echo -e "\033[4mBeispiele\033[0m"
        echo -e "  \033[32mProfil \"${title[2]}\"\033[0m starten und den Computer anschlieÃend \033[31mherunterfahren\033[0m:"
        echo -e "       $0 \033[32m-p${arg[2]}\033[0m \033[31m-s\033[0m\n"
        echo -e "  \033[33m\"/tmp/Quelle1/\"\033[0m und \033[35m\"/Leer zeichen2/\"\033[0m mit \033[36m\"/media/extern\"\033[0m synchronisieren; anschlieÃend \033[31mherunterfahren\033[0m:"
        echo -e "       $0 \033[31m-s\033[0;4mm\033[0m \033[33m/tmp/Quelle1\033[0m \033[4m\"\033[0;35m/Leer zeichen2\033[0;4m\"\033[0m \033[36m/media/extern\033[0m"

        func_exit
}

function func_exit(){
        rm ${exfrom[*]}
        exit 1
}

function func_settings(){
        if [[ "$PROFIL" != "customBak" ]]; then
                # Benötigte Werte aus dem Array holen
                for i in $(seq ${#arg[*]}); do                      # Anzahl der vorhandenen Profile ermitteln
                        if [[ "${arg[$i]}" == "$PROFIL" ]]; then          # wenn das gewünschte Profil gefunden wurde
                                TITLE="${title[$i]}";   ARG="${arg[$i]}"
                                SOURCE="${source[$i]}"; TARGET="${target[$i]}"
                                LOG="${log[$i]}";       EXFROM="${exfrom[$i]}"
                                [[ "${rsync_opt[$i]}" != "" ]] && RSYNC_OPT="${rsync_opt[$i]}"
                        fi
                done
        fi
        [ "$SOURCE" == "/" ] && TARGET="${TARGET}/ROOTFS"    # Workaround für "/"
}

function del_old_backup() {
        # Verzeichnisse älter als $DEL_OLD_BACKUP Tage löschen
        echo "Lösche Backup-Dateien aus ${1}, die älter als ${DEL_OLD_BACKUP} Tage sind..."
        echo "$(date +"%F %R.%S"): Lösche Backup-Dateien aus ${1}, die älter als ${DEL_OLD_BACKUP} Tage sind..." >> ${LOG}
        find "${1}" -maxdepth 1 -type d -mtime +$DEL_OLD_BACKUP -print0 | xargs -0 rm -rfv >> ${LOG}
        # Logfiles löschen (Wenn $TITLE im Namen)
        find "$(dirname $LOG)" -maxdepth 1 -type f -mtime +$DEL_OLD_BACKUP \
       -name "*${TITLE}*" ! -name $(basename $LOG) -print0 | xargs -0 rm -rfv >> ${LOG}
}

######################################### START #########################################

# Wenn eine grafische Oberfläche vorhanden ist, wird u.a. "notify-send" für Benachrichtigungen verwendet, ansonsten immer "echo"
NOTIFY="echo"
[ -n "$DISPLAY" ] && NOTIFY="notify-send"

tty -s && clear
echo -e "\033[44m \033[0m\033[1m RSYNC BACKUP\033[0m\n\033[44m \033[0m 2011 by JaiBee, http://www.321tux.de/\n";

while getopts ":p:am:sd:h" opt
do
        case $opt in
                p) for i in "$OPTARG"; do P="$P $i"; done ;;    # bestimmte(s) Profil(e)
                a) P=${arg[*]} ;;                                                               # alle Profile
                m) # eigene Verzeichnisse an das Skript übergeben
                        for i in "$@"; do                                               # letzte Pfad als Zielverzeichnis
                                [ -d "$i" ] && TARGET="$i";
                        done
                        for i in "$@"; do                                                       # alle übergebenen Verzeichnisse auÃer $TARGET als Quelle
                                [[ -d "$i" && "$i" != "$TARGET" ]] && SOURCE="$SOURCE \"$i\""
                        done
                        TARGET="$(echo $TARGET | sed -e 's/\/$//')"     # Slash am Ende entfernen
                        P="customBak";                                  TITLE="Custom Backup"
                        LOG="$TARGET/$TITLE-log.txt";   MOUNT="" ;;
                s) SHUTDOWN=0 ;;                                                                # Herunterfahren gewählt
                d) DEL_OLD_BACKUP=$OPTARG ;;            # Alte Backups entfernen (Zahl entspricht Tage, die erhalten bleiben)
                h) func_help ;;                                                                 # Hilfe anzeigen
                ?) echo -e "\033[1;41m FEHLER \033[0;1m Option ungültig.\033[0m\n" && func_help ;;
        esac
done

# Sind die benötigen Programme installiert?
which rsync mktemp wall sed $NOTIFY > /dev/null || { echo "Sie benötigen die Programme rsync, mktemp, wall, sed und $NOTIFY zur Ausführung dieses Skriptes."; func_exit; }

# wenn $P leer ist, wurde die Option -p oder -a nicht angegeben
[[ -z "$P" ]] && echo -e "\033[1;41m FEHLER \033[0;1m es wurde kein Profil gewählt\033[0m\n" && func_help

# folgende Zeile auskommentieren, falls zum Herunterfahren des Computers Root-Rechte erforderlich sind
#[[ "$SHUTDOWN" == "0" && "$(whoami)" != "root" ]] && echo -e "\033[1;41m FEHLER \033[0;1m Zum automatischen Herunterfahren sind Root-Rechte erforderlich.\033[0m\n" && func_help

[ "$SHUTDOWN" == "0" ] && echo -e "  \033[1;31mDer Computer wird nach Durchführung des Backups automatisch heruntergefahren!\033[0m"

for PROFIL in $P; do
        func_settings

        # wurden der Option -b gültige Argument zugewiesen?
        [[ "$PROFIL" != "$ARG" && "$PROFIL" != "customBak" ]] && echo -e "\033[1;41m FEHLER \033[0;1m -p wurde nicht korrekt definiert.\033[0m\n" && func_help

        # Konfiguration zu allen gewählten Profilen anzeigen
        echo -e "  \033[4m\nKonfiguration von \033[1m$TITLE\033[0m"
        echo -e "\033[46m \033[0m Quellverzeichnis(se):\033[1m\t$SOURCE\033[0m\n\033[46m \033[0m Zielverzeichnis:\033[1m\t$TARGET\033[0m"
        echo -e "\033[46m \033[0m Log-Datei:\033[1m\t\t$LOG\033[0m"
        if [[ "$PROFIL" != "customBak" ]]; then echo -e "\033[46m \033[0m Exclude:"; sed 's/^/\t\t\t/' $EXFROM ; fi
        [ -n "$DEL_OLD_BACKUP" ] && echo -e "\033[41m \033[0m Backup's:\033[1m\t\tLÃSCHEN wenn älter als $DEL_OLD_BACKUP Tage\033[0m"
done

for PROFIL in $P; do
        func_settings
        func_bak_dir

        # /ROOTFS aus $BAK_DIR entfernen
        BAK_DIR="${BAK_DIR//\/ROOTFS/}"

        # ist die Festplatte eingebunden?
        #[[ "$TARGET" == "$MOUNT"* && ! $(mount | grep "$MOUNT") ]] && echo -e "\033[1;41m FEHLER \033[0;1m Die Festplatte ist nicht eingebunden.\033[0m (\"$MOUNT\")" && func_exit
  if [[ "$TARGET" == "$MOUNT"* && ! $(grep "$MOUNT" /etc/mtab) ]] ; then
     echo "Versuche $MOUNT einzuhängen..."
     mount "$MOUNT"
     [[ ! $(grep "$MOUNT" /etc/mtab) ]] && echo -e "\033[1;41m FEHLER \033[0;1m Die Festplatte ist nicht eingebunden.\033[0m (\"$MOUNT\")" && func_exit
     UNMOUNT=1  # Nach Backup wieder aushängen
  fi

        # ggf. Zielverzeichnisse erstellen
        [ ! -d "$TARGET" ]  && { mkdir -vp "$TARGET" || func_exit ;}
        [ ! -d "$BAK_DIR" ] && { mkdir -p "$BAK_DIR" || func_exit ;}

        echo -e "\n\033[1m$TITLE wird in 5 Sekunden gestartet.\033[0m"
        echo -e "\033[46m \033[0m Zum Abbrechen [Strg] + [C] drücken\n\033[46m \033[0m Zum Pausieren [Strg] + [Z] drücken (Fortsetzen mit \"fg\")\n"
        sleep 5
        $NOTIFY "Backup startet (Profil: \"$TITLE\")"

        # Backup mit rsync starten
        eval rsync $RSYNC_OPT --log-file=\"$LOG\" --exclude-from=\"$EXFROM\" --backup-dir=\"$BAK_DIR\" $SOURCE \"$TARGET\"

        # Funktion zum Löschen alter Backups aufrufen
        [ -n "$DEL_OLD_BACKUP" ] && del_old_backup "$(dirname "$BAK_DIR")"

        echo -e "\a\n\n\033[1m$TITLE wurde abgeschlossen\033[0m\nWeitere Informationen sowie Fehlermeldungen sind in der Datei \"$LOG\" gespeichert.\n"
done

rm ${exfrom[*]}

# Zuvor eingehängtes Ziel wieder aushängen
[ -n "$UNMOUNT" ] && umount $MOUNT

# ggf. Herunterfahren
if [ "$SHUTDOWN" == "0" ] ; then
        # Möglichkeit, das automatische Herunterfahren noch abzubrechen
        $NOTIFY "Backup(s) abgeschlossen. ACHTUNG: Der Computer wird in 5 Minuten heruntergefahren. Führen Sie \"kill -9 $(ps -A | grep -m1 "$(basename "$0")" | cut -d " " -f2)\" aus, um das Herunterfahren abzubrechen."
        sleep 1
        echo "This System is going DOWN for System halt in 5 minutes! Run \"kill -9 $(ps -A | grep -m1 "$(basename "$0")" | cut -d " " -f2)\" to  cancel shutdown." | wall
        echo -en "\a\033[1;41m ACHTUNG \033[0m Der Computer wird in 5 Minuten heruntergefahren.\n\n"
        echo -e "Bitte speichern Sie jetzt alle geöffneten Dokumente oder drücken Sie \033[1m[Strg] + [C]\033[0m,\nfalls der Computer nicht heruntergefahren werden soll.\n"
        sleep 5m
        # verschiedene Befehle zum Herunterfahren mit Benutzerrechten [muss evtl. an das eigene System angepasst werden!]
        # Alle Systeme mit HAL || GNOME DBUS || KDE DBUS || GNOME || KDE
        # Root-Rechte i.d.R. erforderlich für "halt" und "shutdown"!
        dbus-send --print-reply --system --dest=org.freedesktop.Hal /org/freedesktop/Hal/devices/computer org.freedesktop.Hal.Device.SystemPowerManagement.Shutdown || \
        dbus-send --print-reply --dest=org.gnome.SessionManager /org/gnome/SessionManager org.gnome.SessionManager.RequestShutdown || \
        dbus-send --print-reply --dest=org.kde.ksmserver /KSMServer org.kde.KSMServerInterface.logout 0 2 2 || \
        gnome-power-cmd shutdown || dcop ksmserver ksmserver logout 0 2 2 || \
        halt || shutdown -h now
else
        $NOTIFY "Backup(s) abgeschlossen."
fi