Rsync Backup Skript mit Nagios Überwachung

Aus Laub-Home Wiki

Das Ziel ist es ein Backup von einem oder mehrerer Ordner via Rsync auf ein anderes System zu kopieren um dort exakt den selben aktuellen Stand zu haben. Das Skript soll dann anschließend von der Nagios Überwachung geprüft werden ob es denn auch ohne Fehler durchlief.

Voraussetzungen

  • 2 Linux Systeme (hier Debian Linux, 192.168.1.1 und 192.168.1.2)
  • Netzwerk, Internet oder VPN Verbindung zwischen den beiden Rechnern
  • Genug Speicherplatz auf dem Backup System
  • Rsync Port sollte nicht durch eine Firewall geblockt werden (default Port TCP 873)
  • Vorkonfigurierter Nagios Server
  • Vorkonfigurierter NRPE Client auf dem zu sicherndem System

Vorbereitung

Installation Rsync auf beiden Systemen:

aptitude update && aptitude install rsync

Das zu sichernde System (auf dem das Backup Script läuft) sollte via ssh auf das andere System zugreifen können, also bei einem
ssh root@192.168.1.2 sollte keine Passwortabfrage kommen. Wie man dies einrichtet steht hier:
SSH Keygen und SSH-Copy-ID - SSH Zugang ohne Passwort
Nun wird noch ein Backup Folder auf dem Sicherungssystem benötigt:

mkdir /srv/backup

Konfiguration Rsync Daemon

Wenn man den Backup Job über eine unsichere Leitung ausführen will, oder generell ein Rsync über das SSH Protokoll lieber mag, kann man diesen Schritt weglassen.

Auf dem Ziel Rechner, also der PC auf den die Daten gesynct werden, muss der Rsync Daemon konfiguriert werden. Hierzu muss man als erstes in der Datei /etc/default/rsync folgende Zeilen anpassen:

RSYNC_ENABLE=true
RSYNC_NICE='19'

Nun kann der Rsync Dienst überhaupt erst gestartet werden und läuft mit ganz niedriger Priorität (nice -19). Als nächstes muss man in der Datei less /etc/rsyncd.conf einen Pfad vordefinieren. Die Datei existiert standardmäßig unter Debian nicht, sie kann aber mittels cp von der Beispielsdatei kopiert werden:

cp /usr/share/doc/rsync/examples/rsyncd.conf /etc/

Die Datei sollte folgendermaßen aussehen:

# sample rsyncd.conf configuration file

# GLOBAL OPTIONS

#motd file=/etc/motd
#log file=/var/log/rsyncd
# for pid file, do not use /var/run/rsync.pid if
# you are going to run rsync out of the init.d script.
pid file=/var/run/rsyncd.pid
#syslog facility=daemon
#socket options=

# MODULE OPTIONS

[ftp]

        comment = public archive
        path = /var/www/pub
        use chroot = yes
#       max connections=10
        lock file = /var/lock/rsyncd
# the default for read only is yes...
        read only = yes
        list = yes
        uid = nobody
        gid = nogroup
#       exclude =
#       exclude from =
#       include =
#       include from =
#       auth users =
#       secrets file = /etc/rsyncd.secrets
        strict modes = yes
#       hosts allow =
#       hosts deny =
        ignore errors = no
        ignore nonreadable = yes
        transfer logging = no
#       log format = %t: host %h (%a) %o %f (%l bytes). Total %b bytes.
        timeout = 600
        refuse options = checksum dry-run
        dont compress = *.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz

Die Datei sollte dann mindestens so aussehen:

# GLOBAL OPTIONS

pid file=/var/run/rsyncd.pid

# MODULE OPTIONS

[Backup]

        comment = Backup Rsync
        path = /srv/backup
        use chroot = yes
        lock file = /var/lock/rsyncd
        read only = no
        write only = yes
        list = yes
        uid = root
        gid = root
        strict modes = yes
        hosts allow = 192.168.1.1
        ignore errors = no
        ignore nonreadable = yes
        transfer logging = no
        timeout = 600
        refuse options = checksum dry-run
        dont compress = *.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz

Wichtig hierbei wäre der Modulname Backup, die host allow, die path und natürlich die read only und write only Variablen. Hiermit wird dem Host 192.168.1.1 erlaubt Daten auf den Ordner /srv/backup zu schreiben.
Nun kann der Rsync Dienst gestartet werden:

/etc/init.d/rsync start

Wenn nun alles richtig eingerichtet ist sollte man von dem zu Sichernden Rechner folgenden Befehl absetzten können:

rsync 192.168.1.2::

und folgende Ausgabe bekommen:

Backup          Backup Rsync

Da ich den Rsync Daemon aus Sicherheitsgründen nicht dauerhaft aktiviert haben will, sondern ihn manuell beim Backup Start hochfahre und ihn beim Backup Ende wieder herunterfahre, kann dieser aus dem Autostart genommen werden:

update-rc.d -f rsync remove

Backup Skript

Dieses Backup Skript hat folgende Features:

  • Backup via Rsync over SSH oder Rsync mit auf einen Rsync Server
  • Statusmail
  • schreibt ein Logfile welches mit dem Nagios Plugin check_backuplog.sh ausgewertet werden kann
  • Kann mit Excludes Arbeiten
  • Kann mehrere verschiedene Verzeichnisse in das Backup Folder Sichern

Skript Inhalt

rsyncbackup.sh

#!/bin/bash
#########################################################################
#rsyncbackup.sh
#Backup Rsync Script
#by A. Laub
#andreas[-at-]laub-home.de
#
#License:
#This program is free software: you can redistribute it and/or modify it
#under the terms of the GNU General Public License as published by the
#Free Software Foundation, either version 3 of the License, or (at your option)
#any later version.
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
#or FITNESS FOR A PARTICULAR PURPOSE.
#########################################################################
#Set the language
export LANG="en_US.UTF-8"
#Load the Pathes
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

#set the variables:
#Logfile
LOGFILE="/var/log/backup.log"

#Backup Path
#WARNING: No / at end of path
BACKUPPATH="/srv/samba/Bilder /srv/samba/Office /srv/samba/Sicherung"

#Exclude Files (for every exclude you need --exclude: "--exclude *.jpg --exclude *.txt)
#EXCLUDE="--exclude *.tc"

# You want to Limit the Bandwidth (KBpS), uncomment it...
#BANDWIDTH="--bwlimit=120"

#Backup Target
#for Rsync Daemon: Modulename
#for Rsync over SSH: Backup path on target system
BACKUPTARGET="Backup"
#BACKUPTARGET="/srv/samba/"

#User
RSUSER="root"

#Target Host
RSTARGET="192.168.1.2"

#E-Mail Address for Statusmail
MAILADRESS="support@domain.de"

#Senders E-Mail Adress
FROM="$(cat /etc/hostname)@laub-home.de"

#Nagios logfile for check_backuplog.sh
NAGIOSLOGFILE="/var/log/check_backup.log"


#Enable functions:
#Mail Notification (yes/no)
STATUSMAIL="yes"

#Rsync over ssh or to rsync daemon (ssh/rsync)
RSYNCSTYLE="rsync"

#Enable Nagios Monitoring (yes/no)
NAGIOSMONITORING="yes"

##########################################################################
##Functions
##########################################################################

function STARTBLABLA {
echo "#############################################"                            >  $LOGFILE
echo "#Starting sync $(date +"%k:%M %d.%m.%Y"):"                                 >> $LOGFILE
echo ""
}

function RSYNCSERVER {
ssh $RSUSER@$RSTARGET /etc/init.d/rsync start                                   >> $LOGFILE
RSYNCDAEMONSTART=$?
echo "ErrorCode: $RSYNCDAEMONSTART"                                             >> $LOGFILE
for i in $BACKUPPATH ; do
        /usr/bin/rsync --delete -avz --partial --inplace $EXCLUDE $BANDWIDTH --log-file=$LOGFILE $i $RSTARGET::$BACKUPTARGET
        RSYNCERROR=$?
        if [ "$RSYNCERROR" != "0" ]; then
                if [ $NAGIOSMONITORING = yes ]; then
                        NAGIOS
                fi
                echo "Rsync Failure: $RSYNCERROR"                               >> $LOGFILE
                ENDBLABLA
                MAIL
                exit 1
        fi
done
ssh $RSUSER@$RSTARGET /etc/init.d/rsync stop                                    >> $LOGFILE
RSYNCDAEMONSTOP=$?
echo "ErrorCode: $RSYNCDAEMONSTOP"                                              >> $LOGFILE
}

function RSYNCSSH {
for i in $BACKUPPATH ; do
        /usr/bin/rsync --delete -av --progress --partial --inplace $EXCLUDE $BANDWIDTH --log-file=$LOGFILE $i $RSUSER@$RSTARGET:$BACKUPTARGET
        RSYNCERROR=$?
        if [ "$RSYNCERROR" != "0" ]; then
                if [ $NAGIOSMONITORING = yes ]; then
                        NAGIOS
                fi
                echo "Rsync Failure: $RSYNCERROR"                               >> $LOGFILE
                ENDBLABLA
                MAIL
                exit 1
        fi
done
}

function ENDBLABLA {
echo ""                                                                         >> $LOGFILE
echo "#Sync ended $(date +"%k:%M %d.%m.%Y"):"                                    >> $LOGFILE
echo "#############################################"                            >> $LOGFILE
}

function RUNNINGTIME {
# Sekundenzähler stoppen ########################################
ende=$(date +%s)

diff=$[ende-anfang]
echo -e "\n"
RUNTIME="Runtime: $[$diff / 60]min $[$diff % 60]s"
}

function MAIL {
mail -a "From: <$FROM>" -s "$(cat /etc/hostname) Backup" $MAILADRESS           < $LOGFILE
}

function NAGIOSRUNNING {
        MESSAGE="RUNNING: Backup is still running"
        echo "$(date +%Y%m%d%H%M) $MESSAGE" > $NAGIOSLOGFILE
}

function NAGIOS {
if [ "$RSYNCERROR" != "0" ]; then
        MESSAGE="ERROR: Problems at Rsyncjob. - Errorcode: $RSYNCERROR - $RUNTIME"
elif [ "$RSYNCERROR" = "0" ]; then
        MESSAGE="SUCCESS: Backup runs well! - $RUNTIME"
else
        MESSAGE="UNKNOWN: Other Error. - $RUNTIME"
fi
echo "$(date +%Y%m%d%H%M) $MESSAGE" > $NAGIOSLOGFILE
}

##########################################################################
##Execute the functions
##########################################################################

# Sekundenzähler starten ########################################
anfang=$(date +%s)

if [ $NAGIOSMONITORING = yes ]; then
        NAGIOSRUNNING
fi
STARTBLABLA
if [ $RSYNCSTYLE = rsync ]; then
        RSYNCSERVER
elif [ $RSYNCSTYLE = ssh ]; then
        RSYNCSSH
fi
ENDBLABLA
RUNNINGTIME
if [ $STATUSMAIL = yes ]; then
        MAIL
fi
if [ $NAGIOSMONITORING = yes ]; then
        NAGIOS
fi

Einrichtung des Backup Skriptes

Dem Backup Skript ist es eigentlich egal wo es liegt, ich denke ein geeigneter Ort ist zum Beispiel:

/usr/local/sbin/rsyncbackup.sh

Dem Skript sollte man auf jeden Fall noch das execute Recht geben, also am besten:

chmod 755 /usr/local/sbin/rsyncbackup.sh

Wenn dies getan ist sollte man die Skript Variablen nach seinen Bedürfnissen anpassen. Die Variablen sind denke ich ganz gut im Skript beschrieben, deshalb hier kein großartiges blabla dazu.

Automatischen Start einrichten

Dazu verwenden wir den guten alten cron:

crontab -e

dann fügen wir folgende Zeile ein:

10 1 * * * /usr/local/sbin/rsyncbackup.sh > /dev/null 2>&1

Dies bewirkt dass das Skript täglich um 1 Uhr und 10 Minuten gestartet wird und sämtlicher Output unterbunden wird (> /dev/null 2>&1)

Statusmail Beispiel

Wenn man im Skript die Statusmail Variable aktiviert sollte man eine solche Mail nach beenden des Syncs bekommen:

#############################################
#Starting sync 11:19 14.05.2010:
Starting rsync daemon: rsync.
ErrorCode: 0
2010/05/14 11:19:32 [24980] building file list
2010/05/14 11:19:45 [24980] sent 465097 bytes  received 268 bytes  16328.60 bytes/sec
2010/05/14 11:19:45 [24980] total size is 71939383935  speedup is 154587.01
2010/05/14 11:20:00 [24984] building file list
2010/05/14 11:20:02 [24984] sent 50161 bytes  received 282 bytes  2882.46 bytes/sec
2010/05/14 11:20:02 [24984] total size is 27201807002  speedup is 539258.31
2010/05/14 11:20:17 [24988] building file list
2010/05/14 11:20:17 [24988] sent 4129 bytes  received 25 bytes  268.00 bytes/sec
2010/05/14 11:20:17 [24988] total size is 33004548853  speedup is 7945245.27
Stopping rsync daemon: rsync.
ErrorCode: 0

#Sync ended 11:20 14.05.2010:
#############################################

Nagios Überwachung

Um nicht jeden Tag eine E-Mail zu bekommen, soll hier Nagios dafür verantwortlich sein zu prüfen ob das Backup lief oder nicht. Dafür gibt es sicherlich mehrere Möglichkeiten und schon vorhandene Plugins wie check_log, check_log2 und check_logfiles. Die haben aber irgendwie nicht so gewollt wie ich, also habe ich mir das folgende kleine Plugin selbst gebaut.

Skript Inhalt

Hier mein kleines Skript welches den Inhalt des Nagios Backup Logs ausliest. Der Inhalt des Logfiles sollte eine Zeile nicht überschreiten und folgenden Inhalt auf jeden Fall haben:

201005131629 ERROR:
201005131629 SUCCESS:

Das Datum kann mit folgendem Befehl generiert werden:

date +%Y%m%d%H%M

201005131629

check_backuplog.sh

#!/bin/sh
#########################################################################################
#check_backuplog.sh
#by A. Laub andreas[-at-]laub-home.de
#this Script reads a Backup Logfile which contains one line in this format:
#       201005131629 ERROR: Backup has Problems
#   or
#       201005131629 SUCCESS: Backup runs well
#date Format is: date +%Y%m%d%H%M
#
#run script:
#       check_backuplog.sh [LOGFILE] [TIME] [RUNNINGTIME]
#
#License:
#This program is free software: you can redistribute it and/or modify it
#under the terms of the GNU General Public License as published by the
#Free Software Foundation, either version 3 of the License, or (at your option)
#any later version.
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
#or FITNESS FOR A PARTICULAR PURPOSE.
########################################################################################

#Load the Pathes
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
export PATH

#set the variables
#This could be $1 or an hardcoded Logfilepath
LOGFILE="$1"
#Time in hours to get a critical error
TIME="$2"
#Time in hours to get a Warning when script is still running
RUNNINGTIME="$3"

# Don't edit this
if [ "`grep "RUNNING" $LOGFILE`" ]; then
        if [ "`cat $LOGFILE | awk '{print $1}' `" -le "`date -d '-'$RUNNINGTIME' hours' +%Y%m%d%H%M`" ]; then
                echo "WARNING - `cat $LOGFILE`"
                exit 1
        else
                echo "OK - `cat $LOGFILE`"
                exit 0
        fi
fi
if [ ! -f $LOGFILE ]; then
        echo "CRITICAL - Logfile doesn't exist"
        exit 2
fi
if [ "`cat $LOGFILE | awk '{print $1}' `" -le "`date -d '-'$TIME' hours' +%Y%m%d%H%M`" ]; then
        echo "CRITICAL - Backup didn't start within the last $TIME hours"
        exit 2
fi
if [ "`grep "ERROR" $LOGFILE`" ]; then
        echo "CRITICAL - `cat $LOGFILE`"
        exit 2
fi
if [ "`grep "SUCCESS" $LOGFILE`" ]; then
        RUNTIME=$(awk -F": " '{print $3}' $LOGFILE)
        echo "OK - Backup runs well! Runtime: $RUNTIME | runtime=$RUNTIME"
        exit 0
fi
echo "CRITICAL - other Error"
exit 2

Einrichtung Nagios Überwachung

Das oben stehende Skript check_backuplog.sh sollte zu den anderen Nagios Plugins nach /usr/lib/nagios/plugins/ kopiert werden werden. auch diesem Skript sollte man das execute Recht geben:

chmod 755 /usr/lib/nagios/plugins/check_backuplog.sh

Nun wird die NRPE konfiguration angepasst und folgende Zeile

command[check_backuplog]=/usr/lib/nagios/plugins/check_backuplog.sh /var/log/check_backup.log 24 2

der Datei /etc/nagios/nrpe_local.cfg angehängt.
Zur Erklärung dieser Zeile:

command[check_backuplog]=/usr/lib/nagios/plugins/check_backuplog.sh [NagiosBackupLogPath] [ALARMTIME(in hours)] [STILLRUNNINGTIME(in hours)]

Hier steht NagiosBackupLogPath für den Pfad an dem sich das erstellte Nagios Backup Logfile des Rsync Backup Skriptes befindet und ALARMTIME steht für die Zeit nachdem das Skript das nächste mal laufen sollte, ansonsten kommt es zu einem Alarm.

So um das ganze dann noch auf dem Nagios Server einzurichten braucht man noch folgende Zeilen in der Host Konfig des zu überwachenden Systemes (hier der zu sichernde Server)

# Check Backuplog
define service {
        host_name                       laub-samba
        service_description             Backup Log
        check_command                   check_nrpe_1arg!check_backuplog
        use                             generic-service
        notification_interval           0 ; set > 0 if you want to be renotified
}

Voraussetzung hierfür ist eine NRPE Konfigdatei mit folgenden Parametern:

# this command runs a program $ARG1$ with no arguments
define command {
        command_name    check_nrpe_1arg
        command_line    /usr/lib/nagios/plugins/check_nrpe -H $HOSTADDRESS$ -c $ARG1$
}

Nun sollte wenn alles funktioniert in der Nagios Übersichtsseite ein weiterer Check Namens Backup Log auftauchen und bei einem Nagios Logeintrag mit SUCCESS und einem aktuellem TimeStamp ein OK ausgeben. Bei einem ändern des Nagios Backup Logfiles von SUCCESS auf ERROR sollte Nagios alarmieren

Lokale Nagios Config

/etc/nagios-plugins/config/backup.cfg

# 'check_backuplog' command definition
define command{
        command_name    check_backuplog
        command_line    /usr/lib/nagios/plugins/check_backuplog.sh /var/log/check_backup.log 24 2
        }
# Check Backuplog
define service {
        host_name                       laub-samba
        service_description             Backup Log
        check_command                   check_backuplog
        use                             generic-service
        notification_interval           0 ; set > 0 if you want to be renotified
}

Mehr Infos zum einrichten von Nagios findet sich hier:
Nagios3 unter Debian Linux