matze69
Anmeldungsdatum: 23. November 2008
Beiträge: 112
|
Hallo zusammen, ich habe ein kleines Bash-Script geschrieben, das täglich, wöchentlich und monatlich ein verschlüsseltes Backup an mehreren Orten ablegt und alte Backupdateien entfernt. Es sollte täglich per crontab ausgeführt werden. Außerdem muss rsync vorhanden sein, damit es wie vorgesehen funktioniert. Ich stelle das Script hier zur Verfügung, vielleicht ist es ja jemandem nützlich. Außerdem freue ich mich über Tipps und Hinweise zur Verbesserung des Codes. Viele Grüße matze
- backup.sh (2.7 KiB)
- Download backup.sh
|
ChickenLipsRfun2eat
Supporter
Anmeldungsdatum: 6. Dezember 2009
Beiträge: 12070
|
Hallo und danke fürs Teilen! Ich vermute aber, dass du mehr Hinweise über den Code bekommst, wenn er hier im Codeblock steht und kein Download nötig ist.
|
matze69
(Themenstarter)
Anmeldungsdatum: 23. November 2008
Beiträge: 112
|
Gute Idee! Also hier der Code: #!/bin/bash
###########################################
### ###
### (c) 2016 by Matthias Ewering ###
### ###
### matthias.ewering@posteo.de ###
### ###
### !! No warranty whatsoever !! ###
### ###
###########################################
source=/path/to/source #The element to be backed up
daily=/path/to/backup/daily #The directory that will contain the daily backup files
weekly=/path/to/backup/weekly #The directory that will contain the weekly backup files
monthly=/path/to/backup/monthly #The directory that will contain the monthly backup files
main=/path/to/backup #The main backup directory for all backup cycles
mirror1=/path/to/backup_mirror1 #The first mirror of the main backup directory
mirror2=/path/to/backup_mirror2 #The second mirror of the main backup directory
#mirrorn=/foo/bar #The n^th mirror of the main backup directory
tar -czPf ./$(date +"%Y-%m-%d_%H-%M")_backup.tar.gz $source #Create a compressed tarball with the contents to be backed up
gpg --symmetric --cipher-algo aes256 --passphrase secret -o ./$(date +"%Y-%m-%d_%H-%M")_backup.tar.gz.gpg ./*_backup.* #Encrypt the tarball. Remember to replace "secret" with A CUSTOM, SECURE PASSPHRASE!
mv ./*.gpg $daily #Move the encrypted backup file to the main daily backup directory
rm ./*_backup.* #Delete the unencrypted tarball
find $daily -type f | sort -rd | sed -e '1,7d' | xargs -d '\n' rm -- #Delete any file from the main daily backup directory with the 8th oldest timestamp or older
if [ $(date +"%u") = "7" ] #
#
then find $daily -type f | sort -d | sed -e'1,6d' | xargs cp -t $weekly #
#On a Sunday, copy the latest daily backup file to the weekly backup directory,...
find $weekly -type f | sort -rd | sed -e '1,5d' | xargs -d '\n' rm -- #...then delete any file from the weekly backup directory with the 6th oldest...
#...timestamp or older
fi #
if [ $(date +"%d") = "01" ] #
#On the first of a month, copy the latest daily backup file to the monthly backup directory
then find $daily -type f | sort -d | sed -e'1,6d' | xargs cp -t $monthly #
#
fi #
rsync -a --delete $main $mirror1 #Synchronize the first mirror directory with the main backup directory
rsync -a --delete $main $mirror2 #Synchronize the second mirror directory with the main backup directory
#rsync -a --delete $main $mirrorn #Synchronize the n^th mirror directory with the main backup directory
exit 0
|
matze69
(Themenstarter)
Anmeldungsdatum: 23. November 2008
Beiträge: 112
|
Kann mir jemand verraten, warum der Thread gemeldet wurde...?
|
senden9
Anmeldungsdatum: 8. Februar 2010
Beiträge: 965
|
Nur Zum Stil: Ich mag es persönlich lieber wenn die Dokumentation und die Optionen für den Endanwender (Zeile 13-20) in einer separaten readme.md oder in einem Kommentarblock am Anfang der Datei stehen.
Im jetzigen Format sieht das ganze in einem Terminal in einem kleinen Fenster etwas zerrissen aus (wegen den vielen Leerzeichen).
|
ChickenLipsRfun2eat
Supporter
Anmeldungsdatum: 6. Dezember 2009
Beiträge: 12070
|
matze69 schrieb: Kann mir jemand verraten, warum der Thread gemeldet wurde...?
Weil es besser in "Projekte" passt, da es dein Projekt ist und keine Supportanfrage enthält. Zumal es da nicht so schnell "untergeht". Das dient dem Aufräumen und dem Einsortieren in die richtige Kategorie. "Melden" ist nicht automatisch "böse" ☺ Für mehr Details siehe Richtig fragen und die jeweiligen Forenstickies mit dem Titel "Welche Themen gehören hier her und welche nicht?"
|
matze69
(Themenstarter)
Anmeldungsdatum: 23. November 2008
Beiträge: 112
|
Danke senden9! Für (meinen) Hausgebrauch habe ich lieber alles in einer Datei. Wer gern Teile auslagern möchte, kann das Script natürlich gern nach seinem Gusto ändern 😉
|
matze69
(Themenstarter)
Anmeldungsdatum: 23. November 2008
Beiträge: 112
|
Danke auch Dir, Chicken. Das Thema kann gern verschoben werden!
|
track
Anmeldungsdatum: 26. Juni 2008
Beiträge: 7174
|
Noch ein Kommentar zum Handwerklichen: Du erlaubst ja in den Zeilen 13 ... 20 beliebige Pfade, also auch mit Leer- und Sonderzeichen drin. Konsequenterweise musst Du dann auch den Aufruf aller dieser Variablen im Skript später immer "quoten", damit nicht im Falle besagter Leer- oder Sonderzeichen ein Unglück geschieht. - Das solltest Du also auf jeden Fall noch nachtragen. LG, track
|
matze69
(Themenstarter)
Anmeldungsdatum: 23. November 2008
Beiträge: 112
|
Ein guter Hinweis, danke sehr! Ich habe die quotes eingefügt.
|
track
Anmeldungsdatum: 26. Juni 2008
Beiträge: 7174
|
... nur leider nicht in den hier veröffentlichen Versionen ! - die sind beide noch unkorrigiert. Bitte schreib die korrigierte Version auch hier irgendwo hin, damit die Leute die korrigierte Variante benutzen können. Oder möchtest Du, dass jeder für sich das nochmal korrigiert ? 😉 LG, track
|
matze69
(Themenstarter)
Anmeldungsdatum: 23. November 2008
Beiträge: 112
|
Keineswegs 😉 Hier die aktuelle Fassung: #!/bin/bash
###########################################
### ###
### (c) 2016 by Matthias Ewering ###
### ###
### matthias.ewering@posteo.de ###
### ###
### !! No warranty whatsoever !! ###
### ###
###########################################
source=/path/to/source #The element to be backed up
daily=/path/to/backup/daily #The directory that will contain the daily backup files
weekly=/path/to/backup/weekly #The directory that will contain the weekly backup files
monthly=/path/to/backup/monthly #The directory that will contain the monthly backup files
main=/path/to/backup #The main backup directory for all backup cycles
mirror1=/path/to/backup_mirror1 #The first mirror of the main backup directory
mirror2=/path/to/backup_mirror2 #The second mirror of the main backup directory
#mirrorn=/foo/bar #The n^th mirror of the main backup directory
tar -czPf ./$(date +"%Y-%m-%d_%H-%M")_backup.tar.gz "$source" #Create a compressed tarball with the contents to be backed up
gpg --symmetric --cipher-algo aes256 --passphrase secret -o ./$(date +"%Y-%m-%d_%H-%M")_backup.tar.gz.gpg ./*_backup.* #Encrypt the tarball. Remember to replace "secret" with A CUSTOM, SECURE PASSPHRASE!
mv ./*.gpg "$daily" #Move the encrypted backup file to the main daily backup directory
rm ./*_backup.* #Delete the unencrypted tarball
find "$daily" -type f | sort -rd | sed -e '1,7d' | xargs -d '\n' rm -- #Delete any file from the main daily backup directory with the 8th oldest timestamp or older
if [ $(date +"%u") = "7" ]
then find "$daily" -type f | sort -d | sed -e'1,6d' | xargs cp -t "$weekly"
#On a Sunday, copy the latest daily backup file to the weekly backup directory,...
find "$weekly" -type f | sort -rd | sed -e '1,5d' | xargs -d '\n' rm -- #...then delete any file from the weekly backup directory with the 6th oldest...
#...timestamp or older
fi
if [ $(date +"%d") = "01" ]
#On the first of a month, copy the latest daily backup file to the monthly backup directory
then find "$daily" -type f | sort -d | sed -e'1,6d' | xargs cp -t "$monthly"
fi
rsync -a --delete "$main" "$mirror1" #Synchronize the first mirror directory with the main backup directory
rsync -a --delete "$main" "$mirror2" #Synchronize the second mirror directory with the main backup directory
#rsync -a --delete "$main" "$mirrorn" #Synchronize the n^th mirror directory with the main backup directory
exit 0
- backup.sh (2.4 KiB)
- Download backup.sh
|
matze69
(Themenstarter)
Anmeldungsdatum: 23. November 2008
Beiträge: 112
|
Ich habe das Script um eine Funktion erweitert, die nach Ablauf eines Jahres die monatlichen Sicherungen in einen Archivordner verschiebt. Meine Lösung dazu scheint mir leider etwas umständlich, kennt jemand eine elegantere Methode? Hier der aktuelle Code: #!/bin/bash
###########################################
### ###
### (c) 2016 by Matthias Ewering ###
### ###
### matthias.ewering@posteo.de ###
### ###
### !! No warranty whatsoever !! ###
### ###
###########################################
source=/path/to/source #The element to be backed up
daily=/path/to/backup/daily #The directory that will contain the daily backup files
weekly=/path/to/backup/weekly #The directory that will contain the weekly backup files
monthly=/path/to/backup/monthly #The directory that will contain the monthly backup files
main=/path/to/backup #The main backup directory for all backup cycles
mirror1=/path/to/backup_mirror1 #The first mirror of the main backup directory
mirror2=/path/to/backup_mirror2 #The second mirror of the main backup directory
#mirrorn=/foo/bar #The n^th mirror of the main backup directory
tar -czPf ./$(date +"%Y-%m-%d_%H-%M")_backup.tar.gz "$source" #Create a compressed tarball with the contents to be backed up
gpg --symmetric --cipher-algo aes256 --passphrase secret -o ./$(date +"%Y-%m-%d_%H-%M")_backup.tar.gz.gpg ./*_backup.* #Encrypt the tarball. Remember to replace "secret" with A CUSTOM, SECURE PASSPHRASE!
mv ./*.gpg "$daily" #Move the encrypted backup file to the main daily backup directory
rm ./*_backup.* #Delete the unencrypted tarball
find "$daily" -type f | sort -rd | sed -e '1,7d' | xargs -d '\n' rm -- #Delete any file from the main daily backup directory with the 8th oldest timestamp or older
if [ $(date +"%u") = "7" ]
then find "$daily" -type f | sort -d | sed -e '1,6d' | xargs cp -t "$weekly"
#On a Sunday, copy the latest daily backup file to the weekly backup directory,...
find "$weekly" -type f | sort -rd | sed -e '1,5d' | xargs -d '\n' rm -- #...then delete any file from the weekly backup directory with the 6th oldest...
#...timestamp or older
fi
if [ $(find "$daily" -type f | sort -rd | awk -F '/' '{print $NF}' | cut -c1-4 | head -2 | tail -1) -lt $(date +"%Y") ]
#When a new year has begun, create an archive directory for...
then mkdir "$main"/$(($(date +"%Y") - 1)) #...the old year and move the monthly files to that archive directory
mv "$monthly"/*.gpg "$main"/$(($(date +"%Y") - 1))
fi
if [ $(date +"%d") = "01" ]
#On the first of a month, copy the latest daily backup file to the monthly backup directory
then find "$daily" -type f | sort -d | sed -e '1,6d' | xargs cp -t "$monthly"
fi
rsync -a --delete "$main" "$mirror1" #Synchronize the first mirror directory with the main backup directory
rsync -a --delete "$main" "$mirror2" #Synchronize the second mirror directory with the main backup directory
#rsync -a --delete "$main" "$mirrorn" #Synchronize the n^th mirror directory with the main backup directory
exit 0
edit: Fehler in der Sortierung bereinigt.
- backup.sh (2.9 KiB)
- Download backup.sh
|
matze69
(Themenstarter)
Anmeldungsdatum: 23. November 2008
Beiträge: 112
|
Hallo, ich habe das Script komplett neu geschrieben. Dadurch sind einige mögliche Fehlerquellen eliminiert für den Fall, dass das Script in bei einem vorherigen Termin einmal nicht korrekt durchgelaufen sein sollte. Wie immer freue ich mich über Tipps und Hinweise zur Verbesserung des Codes. #!/bin/bash
# Define the directory structure:
source=/path/to/source
destination=/path/to/destination
daily="$destination"/daily
weekly="$destination"/weekly
monthly="$destination"/monthly
mirror_1=/path/to/mirror_1
mirror_2=/path/to/mirror_2
# Create a tarball containing the data:
tar -czPf ./$(date +"%Y%m%d")_backup.tar.gz $source
# Encrypt the tarball to the daily backup directory.
# Hint: You may also give the passphrase as a string
# rather than reading it from an external file.
gpg --symmetric --cipher-algo aes256 --passphrase $(cat /path/to/passphrase.txt) -o "$daily"/$(date +"%Y%m%d")_backup.tar.gz.gpg ./*_backup.tar.gz
# Delete the unencrypted tarball:
rm ./*_backup.tar.gz
# Delete the 8th oldest (and older) daily backup file(s):
find "$daily" -type f | sort -rd | sed -e '1,7d' | xargs -d '\n' rm -f
# If the calendar week in the 2nd most recent daily backup file's
# timestamp does not match the current calendar week, copy the oldest
# daily backup fily to the weekly backup directory and then delete
# the 6th oldest (and older) weekly backup file(s):
if [ $(date -d $(find "$daily" -type f | sort -d | awk -F / '{print $NF}' | tail -n2 | head -n1 | cut -c1-8) +%V) -ne $(date +%V) ] ;
then
find "$daily" -type f | sort -d | head -n1 | xargs cp -t "$weekly"
find "$weekly" -type f | sort -rd | sed -e '1,5d' | xargs -d '\n' rm -f
fi
# If the month in the latest weekly backup file's timestamp does not
# match the current month, copy the oldest weekly backup file to the
# monthly backup directory:
if [ $(find "$weekly" -type f | sort -d | awk -F / '{print $NF}' | tail -n1 | cut -c5-6) -ne $(date +%m) ] ;
then
find "$weekly" -type f | sort -d | head -n1 | xargs cp -t "$monthly"
fi
# Move each backup file in the monthly backup directory whose timestamp's
# year does not match the current year to an archive directory for the
# pertaining year. If no appropriate archive direcotry exists, create it
# first:
for i in `find "$monthly" -type f` ; do
if [ $(echo $i | awk -F / '{print $NF}' | cut -c1-4) -ne $(date +%Y) ] ;
then
year=$(echo $i | awk -F / '{print $NF}' | cut -c1-4)
if [ $(find "$destination" -maxdepth 1 -type d -name "*$year*" | wc -l) -ne 0 ] ;
then
mv $i "$destination"/"$year"
else
mkdir "$destination"/"$year"
mv $i "$destination"/"$year"
fi
fi
done
# Synchronize the entire backup set to mirror1:
rsync -a --delete "$destination" "$mirror_1"
# Synchronize the entire backup set to mirror2:
rsync -a --delete "$destination" "$mirror_2"
- backup.sh (2.7 KiB)
- Download backup.sh
|
matze69
(Themenstarter)
Anmeldungsdatum: 23. November 2008
Beiträge: 112
|
Hallo, und noch ein Update: Ich habe eine Funktion hinzugefügt, die nach jedem Updatezyklus eine Mail versendet und so über Dauer und Größe des aktuellen Backups sowie des gesamten Datensatzes informiert. Außerdem wird ersichtlich, welche Backupaufrufe an dem entsprechenden Tag gemacht wurden. Damit das Reporting per Mail funktioniert, muss msmtp installiert und natürlich zum Versenden von Mails konfiguriert sein. Wie immer freue ich mich über Tipps und Hinweise zur Verbesserung des Codes. #!/bin/bash
# Keep track of time:
SECONDS=0
starttime=$(date)
# Initialize job control variables:
dailydone=0
weeklydone=0
monthlydone=0
yearlydone=0
# Define the directory structure:
source=/path/to/source
destination=/path/to/destination
daily="$destination"/daily
weekly="$destination"/weekly
monthly="$destination"/monthly
mirror_1=/path/to/mirror_1
mirror_2=/path/to/mirror_2
mirror_3=/path/to/mirror_3
# Create a tarball containing the data:
tar -czPf ./$(date +"%Y%m%d")_backup.tar.gz $source
# Encrypt the tarball to the daily backup directory.
# Hint: You may also give the passphrase as a string
# rather than read it from an external file.
gpg --symmetric --cipher-algo aes256 --passphrase $(cat /path/to/backuppass.txt) -o "$daily"/$(date +"%Y%m%d")_backup.tar.gz.gpg ./*_backup.tar.gz
# Delete the unencrypted tarball:
rm ./*_backup.tar.gz
# Delete the 8th oldest (and older) daily backup file(s):
find "$daily" -type f | sort -rd | sed -e '1,7d' | xargs -d '\n' rm -f
dailydone=1
# If the calendar week in the 2nd most recent daily backup file's
# timestamp does not match the current calendar week, copy the oldest
# daily backup fily to the weekly backup directory and then delete
# the 6th oldest (and older) weekly backup file(s):
if [ $(date -d $(find "$daily" -type f | sort -d | awk -F / '{print $NF}' | tail -n2 | head -n1 | cut -c1-8) +%V) -ne $(date +%V) ] ;
then
find "$daily" -type f | sort -d | head -n1 | xargs cp -t "$weekly"
find "$weekly" -type f | sort -rd | sed -e '1,5d' | xargs -d '\n' rm -f
weeklydone=1
fi
# If the month in the latest weekly backup file's timestamp does not
# match the current month, copy the oldest weekly backup file to the
# monthly backup directory:
if [ $(find "$weekly" -type f | sort -d | awk -F / '{print $NF}' | tail -n1 | cut -c5-6) -ne $(date +%m) ] ;
then
find "$weekly" -type f | sort -d | head -n1 | xargs cp -t "$monthly"
monthlydone=1
fi
# Move each backup file in the monthly backup directory whose timestamp's
# year does not match the current year to an archive directory for the
# pertaining year. If no appropriate archive direcotry exists, create it
# first:
for i in `find "$monthly" -type f` ; do
if [ $(echo $i | awk -F / '{print $NF}' | cut -c1-4) -ne $(date +%Y) ] ;
then
year=$(echo $i | awk -F / '{print $NF}' | cut -c1-4)
yearlydone=1
if [ $(find "$destination" -maxdepth 1 -type d -name "*$year*" | wc -l) -ne 0 ] ;
then
mv $i "$destination"/"$year"
else
mkdir "$destination"/"$year"
mv $i "$destination"/"$year"
fi
fi
done
# Keep track of time:
timestamp_0=$SECONDS
# Synchronize the entire backup set to mirror_1:
rsync -a --delete "$destination" "$mirror_1"
# Keep track of time:
timestamp_1=$(( $SECONDS - $timestamp_0 ))
# Synchronize the entire backup set to mirror_2:
rsync -a --delete "$destination" "$mirror_2"
# Keep track of time:
timestamp_2=$(( $SECONDS - $timestamp_0 - $timestamp_1 ))
# Synchronize the entire backup set to mirror_3:
rsync -a --delete "$destination" "$mirror_3"
# Keep track of time:
timestamp_3=$(( $SECONDS - $timestamp_0 - $timestamp_1 - $timestamp_2 ))
endtime=$(date)
# Send a notification after the backup cycle is complete:
echo "From: Backup script <donotreply@backup.sys>" >> ./mailtext
echo "To: Herr/Frau Empfänger(in) <name@e-mail.net>" >> ./mailtext
echo "Date: $(date)" >> ./mailtext
echo "Subject: [$(date +%Y/%m/%d)] Daily backup report" >> ./mailtext
echo -e "\n" >> ./mailtext
echo " +++ BEGIN MESSAGE +++" >> ./mailtext
echo " " >> ./mailtext
echo " " >> ./mailtext
echo "Startzeit: $starttime" >> ./mailtext
echo "Endzeit: $endtime" >> ./mailtext
echo " " >> ./mailtext
echo " " >> ./mailtext
echo "Gesamtdauer: $(($SECONDS/3600))h $(($SECONDS/60))m $(($SECONDS % 60))s" >> ./mailtext
echo " " >> ./mailtext
echo "Master: $(($timestamp_0/3600))h $(($timestamp_0/60))m $(($timestamp_0 % 60))s" >> ./mailtext
echo "Mirror 1: $(($timestamp_1/3600))h $(($timestamp_1/60))m $(($timestamp_1 % 60))s" >> ./mailtext
echo "Mirror 2: $(($timestamp_2/3600))h $(($timestamp_2/60))m $(($timestamp_2 % 60))s" >> ./mailtext
echo "Mirror 3: $(($timestamp_3/3600))h $(($timestamp_3/60))m $(($timestamp_3 % 60))s" >> ./mailtext
echo " " >> ./mailtext
echo " " >> ./mailtext
if [ $dailydone -eq 1 ] ;
then
echo "Täglich: JA" >> ./mailtext
else
echo "Täglich: NEIN" >> ./mailtext
fi
if [ $weeklydone -eq 1 ] ;
then
echo "Wöchentlich: JA" >> ./mailtext
else
echo "Wöchentlich: NEIN" >> ./mailtext
fi
if [ $monthlydone -eq 1 ] ;
then
echo "Monatlich: JA" >> ./mailtext
else
echo "Monatlich: NEIN" >> ./mailtext
fi
if [ $yearlydone -eq 1 ] ;
then
echo "Jährlich: JA" >> ./mailtext
else
echo "Jährlich: NEIN" >> ./mailtext
fi
echo " " >> ./mailtext
echo " " >> ./mailtext
echo "Größe: $(du -h $daily | tail -n1 | awk '{print $1}')" >> ./mailtext
echo "Gesamtgröße: $(du -h $destination | tail -n1 | awk '{print $1}')" >> ./mailtext
echo " " >> ./mailtext
echo " " >> ./mailtext
echo " +++ END MESSAGE +++" >> ./mailtext
echo -e "\n" >> ./mailtext
msmtp -a default name@e-mail.net < ./mailtext
rm -f ./mailtext
|