Backupscript
Hier ein Script welches Dateien und MySQL-Datenbanken sichern kann.
In den ersten Zeilen steht auch wie man es installiert.
#!/bin/bash # ### Installation: ## Auf jeweiligem Server per SSH verbinden und folgendes ausführen: ## touch /usr/local/bin/backup.sh ## chmod a+x /usr/local/bin/backup.sh && ln -s /usr/local/bin/backup.sh /etc/cron.daily/ && vi /usr/local/bin/backup.sh ## ## In die neue Datei diesen Inhalt hineinkopieren und die Variablen anpassen, danach Fertig. # Datensicherungsziel OHNE abschliessenden Slash DEST="/datensicherung" TMPDIR="${DEST}/tmpbackup" BACKUPLOG=${DEST}/${BINHOSTNAME}-backup.log MAILRCPT="<EMPFÄNGER_MAILADRESSE>" # Dateien loeschen die aelter als X Minuten sind (1440 = 24 Stunden) OLDMIN="1380" # 23 Stunden # MySQL Zugangsdaten DBHOST="" DBUSER="" DBPASS="" # MySQL Datenbanken (Leerzeichen getrennt) DBS="" DBIGNORE="(^mysql|_schema)" # Grep Regex # MongoDB Zugangsdaten MONGODBUSER="" MONGODBPASS="" # Datei -/Ordnerpfade (Leerzeichen getrennt, ohne abschliessenden Slash) DIRS="" #### Ab hier Finger weg, wenn keine Ahnung #### # binary Pfade BINHOSTNAME=`which hostname` BINMYSQLDUMP=`which mysqldump` BINTAR=`which tar` BINGZIP=`which gzip` BINCAT=`which cat` BINFIND=`which find` BINRM=`which rm` BINMOUNT=`which mount` BINUMOUNT=`which umount` BINDOCKER=`which docker` BINDOCKERCOMPOSE=`which docker-compose` BINMAIL=`which mail` BINSENDMAIL=`which sendmail` BINSSMTP=`which ssmtp` DOCKERCONTAINERDIR="/var/lib/docker/volumes" # Timestamp fuer logging LOGTS () { date "+%b %d %Y %H:%M:%S" } # Filename prefix FILEPREFIX="$(date +%Y-%m-%d_%H-%M).`${BINHOSTNAME} -s`" # # Mount Check # ERROR=0 if grep -qs "${DEST}" /proc/mounts; then echo "${LOGTS} It's mounted." if touch "${DEST}/test.touch" 2>/dev/null; then rm "${DEST}/test.touch" echo "${LOGTS} It's writeable." else echo "${LOGTS} WARNUNG: Ziel nicht beschreibbar." ERROR="1" fi else echo "${LOGTS} WARNUNG: Ziel nicht gemounted." ERROR=1 fi if [ ${ERROR} != 0 ]; then echo "${LOGTS} WARNUNG: Versuche mount!" ${BINUMOUNT} ${DEST} 2>/dev/null ${BINMOUNT} ${DEST} if touch "${DEST}/test.touch" 2>/dev/null; then rm "${DEST}/test.touch" echo "${LOGTS} It's writeable." else echo "${LOGTS} WARNUNG: Ziel immer noch nicht beschreibbar." exit 1 fi fi function db_backup () { # # MySQL # if [ ! -z "$DBUSER" ]; then DBS=$(/usr/bin/mysql -u$DBUSER -p$DBPASS -h$DBHOST --batch --disable-column-names -e "SHOW DATABASES;") if [ ! -z "$DBIGNORE" ]; then DBS=$(echo "$DBS" | grep -vE "$DBIGNORE") fi for db in ${DBS} do echo "$(LOGTS): sichere Datenbank: $db" /usr/local/bin/mysqldump -u${DBUSER} --password=${DBPASS} -h $DBHOST --opt $db > "${DEST}/${FILEPREFIX}.$db.sql" done if [ $? -eq 0 ]; then DBBACKUP=0 else DBBACKUP=1 fi fi } function influxdb_backup () { # # Influxdb # INFLUXCONTAINER=$(${BINDOCKER} ps -f "name=influxdb2" --format "{{.ID}}") echo "$(LOGTS): sichere Influxdb" ${BINDOCKER} exec -t ${INFLUXCONTAINER} influx backup /backup/${FILEPREFIX}-influx -t <INFLUXDB_TOKEN> if [ $? -eq 0 ]; then INFLUXDBBACKUP=0 else INFLUXDBBACKUP=1 fi mv <PFAD_ZU_EXT_BACKUPDIR_AUSSERHALB_DES_CONTAINERS/${FILEPREFIX}-influx ${DEST} } unction mongodb_backup () { # # mongodb # echo "$(LOGTS): sichere Mongodb" MONGODBLIST=$(${BINDOCKER} exec mongodb sh -c "mongo -u ${MONGODBUSER} -p ${MONGODBPASS} --quiet --eval \"printjson(db.adminCommand('listDatabases'))\"| jq '.databases[].name' | tr -d '\"'") for mdb in $MONGODBLIST do ${BINDOCKER} exec mongodb sh -c "exec mongodump -u ${MONGODBUSER} -p ${MONGODBPASS} --authenticationDatabase admin --quiet --tlsInsecure --db ${mdb} --archive --gzip --dumpDbUsersAndRoles > /backup/mongodb-${mdb}-$FILEPREFIX.archive.gz" done if [ $? -eq 0 ]; then MONGODBBACKUP=0 else MONGODBBACKUP=1 fi } function paperless_backup () { # # Paperless # ## backup paperless echo "$(LOGTS): sichere Paperless" ${BINDOCKER} exec -t paperless-ngx document_exporter ../export -d -z if [ $? -eq 0 ]; then PAPERLESSBACKUP=0 else PAPERLESSBACKUP=1 fi } function file_backup () { # # Dateien # echo "${LOGTS} sichere Dateien: ${DIRS}" ${BINTAR} -zcvf "${DEST}/${FILEPREFIX}.files.tar.gz" ${DIRS} 1> /dev/null CONTAINER=$(ls <PFAD_ZU_DOCKER_COMPOSE_PROJEKTEN>) ## stop containers for application in ${CONTAINER} do echo "$(LOGTS): Stoppe Docker Container: $application." ${BINDOCKER} compose -f ${DOCKERCONTAINERDIR}/$application/docker-compose.yml pause done # sync files echo "$(LOGTS): sichere Dateien aus: ${DIRS}" mkdir ${TMPDIR} rsync -a ${DIRS} ${TMPDIR} if [ $? -eq 0 ]; then FILEBACKUP=0 else FILEBACKUP=1 fi ## start containers for application in ${CONTAINER} do echo "$(LOGTS): Starte Docker Container: $application." ${BINDOCKER} compose -f ${DOCKERCONTAINERDIR}/$application/docker-compose.yml unpause done # tar synced files echo "$(LOGTS): Erstelle Archiv aus : ${TMPDIR}" ${BINTAR} -cvf "${DEST}/${FILEPREFIX}.files.tar" ${TMPDIR}/* 1> /dev/null # ${BINTAR} -zcvf "${DEST}/${FILEPREFIX}.files.tar.gz" ${TMPDIR}/* 1> /dev/null if [ $? -eq 0 ]; then FILETARBACKUP=0 else FILETARBACKUP=1 fi echo "$(LOGTS): Archiv erstellt, rämue auf." rm -r ${TMPDIR} } function file_purge () { # # Alte Backups loeschen # echo "$(LOGTS): loesche Backups welche aelter als ${OLDMIN} Sekunden sind" ${BINFIND} ${DEST}/ -type f \( -iname \*.tar -o -iname \*.sql \) -mmin +${OLDMIN} -exec ${BINRM} {} \; ${BINFIND} ${DEST}/ -type d -name "*-influx" -mmin +${OLDMIN} -exec ${BINRM} -r {} \; } function send_mail () { # # Mail Backup-Log # if ! [[ "1" =~ ^(${DBBACKUP}|${INFLUXDBBACKUP}|${MONGODBBACKUP}|${PAPERLESSBACKUP}|${FILEBACKUP}|${FILETARBACKUP})$ ]]; then #if [ "${DBBACKUP}" -eq 0 ] && [ "${INFLUXDBBACKUP}" -eq 0 ] && [ "${FILEBACKUP}" -eq 0 ] && [ "${FILETARBACKUP}" -eq 0 ]; then SUBJECT="OK: $(hostname)_Backup" else SUBJECT="WARN: $(hostname)_Backup-Fehler" fi echo "$(LOGTS): Versende Mail" #####${BINMAIL} ${MAILRCPT} -s ${SUBJECT} << EOF #####${BINSENDMAIL} ${MAILRCPT} << EOF #####${BINSSMTP} ${MAILRCPT} << EOF subject:"${SUBJECT}" Die erstellten Sicherungsdateien sind: `ls -lh -d ${DEST}/${FILEPREFIX}*|awk '{printf "%-4s %-3s %-2s %-5s %s\n", $5, $6, $7, $8,$9}'` Informationen zum Sicherungslog: `ls -l ${BACKUPLOG}|awk '{print $9}'` `cat ${BACKUPLOG}|grep "$(date "+%b %d %Y")"` echo "Errorlevel von DBBACKUP ${DBBACKUP}" echo "Errorlevel von INFLUXDBBACKUP ${INFLUXDBBACKUP}" echo "Errorlevel von MONGODBBACKUP ${MONGODBBACKUP}" echo "Errorlevel von PAPERLESSBACKUP ${PAPERLESSBACKUP}" echo "Errorlevel von FILEBACKUP ${FILEBACKUP}" echo "Errorlevel von TARBACKUP ${FILETARBACKUP}" EOF } #DBBACKUP=0 #INFLUXDBBACKUP=0 #MONGODBBACKUP=1 #PAPERLESSBACKUP=0 #FILEBACKUP=0 #FILETARBACKUP=0 db_backup influxdb_backup mongodb_backup paperless_backup file_backup file_purge send_mail exit 0
Inkrementelles Backup
Damit man täglich nicht immer die selbe Menge sichern muss, sondern nur die Änderungen, weist man tar
an eine „Inkrementelle Sicherung“ zu erstellen.
Man fügt zum tar-Befehl einfach den Parameter -g <PFAD_ZU>/<SNAPSHOTFILE>
hinzu.
Um dann zwischendurch noch Komplette Sicherungen zu erstellen kommt noch wahlweise der Parameter –level=0
In unserem Script fügt man oben einen neuen Parameter hinzu und ändert folgende Zeile:
+++ SNAPFILE=${DEST}/snap.snar --- ${BINTAR} -zcvf "${DEST}/${FILEPREFIX}.files.tar.gz" ${DIRS} 1> /dev/null +++ ${BINTAR} -zcvf "${DEST}/${FILEPREFIX}.files.tar.gz" -g ${SNAPFILE} $1 ${DIRS} 1> /dev/null
Nun fügt man in der /etc/crontab
diese Zeilen hinzu, um z.B. Sonntags eine komplette und an den sonstigen Tagen einen inkrementelle Sicherung zu erstellen.
# m h dom mon dow user command <MINUTE> <STUNDE> * * 0 root <PFAD_ZU>/backup.sh "--level=0" > <PFAD_ZU_FULLBACKUP_LOG> <MINUTE> <STUNDE> * * 1-6 root <PFAD_ZU>/backup.sh > <PFAD_ZU_INKBACKUP_LOG>