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
|