backup script review

dagnu

Well-Known Member
Tachchen,

nachdem mein Plünich-Pseudo-RAID Controller (Promise) letzte Woche mal wieder den
Dienst versagte, sah ich mich gezwungen mal in ein USB HDD Gehäuse zu investieren.
Was mir dann eigentlich nur fehlte war ein Backup-Skript.

Folgende Überlegungen:
* inkrementelles dump der Systempartitionen (ähnlich wie im Wiki, nur ohne cron, da
mein Rechenknecht nicht jede Nacht durchrennt)
* Synchronisation von /home und /share

Rausgekommen ist dann das angefügte awk Skript und die entsprechende
Konfigurationsdatei. Möglich sind die Angaben dump, nodump und sync.
Die dumps werden in der in level festgelegten Reihenfolge angelegt, dabei
wird der angegebene Dateiname um das aktuelle Datum, eine Kennung für das
dump Level und die Nummer der Reihenfolge ergänzt.
Bisher habe ich leider noch keine Idee, wie ich das Skript beim
Herunterfahren anwerfen kann (stfw - ich weis...).

Vieleicht kann es ja noch jemand gebrauchen.
Weiterhin würde ich mich über Verbesserungsvorschläge und Anregungen freuen.

Aufruf:
Code:
backup.awk < backup.conf

cat backup.conf:

Code:
# Konfiguration für Backup Skript

# Wohin soll gesichert werden?
# dst /absoluter/Pfad
dst /mnt/usb

# In welchen Level Reihenfolgen soll gesichert werden?
level 0 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 2 2 2 2 2

# Welche Verzeichnisse sollen nicht gesichert werden?
# nodump /absoluter/Pfad
nodump /usr/local/portsnap
nodump /usr/ports
nodump /usr/src
nodump /usr/obj

# Welche Partitionen sollen gesichert werden?
# dump /absoluter/Pfad NameDerSicherungsdatei
dump / root
dump /opt opt
dump /usr usr
dump /var var

# Welche Verzeichnisse sollen synchronisiert werden?
# Erfordert rsync (/usr/ports/net/rsync)!
# sync /absoluter/Pfad
sync /mnt/ar0usr/home
sync /share

cat backup.awk
Code:
#!/usr/bin/awk -f
/^dst/ { dst=$2 }
/^level/ { for(i = 2; i <= NF; i++) { levels[i - 1] = $i } }
/^nodump/ { nodumps[$2]++ }
/^dump/ { dumps[$2] = $3 }
/^sync/ { syncs[$2]++ }
END {
  # nodumps
  print "Setze nodump flag:"
  for(path in nodumps) {
    print path
    if(system("chflags -R nodump " path))
      errors[++error] = "nodump " path " > Setzen des nodump flags nicht möglich."
    else
      results[++result] = "nodump " path
  }
  # dumps
  print "Sichere Partitionen:"
  for(path in dumps) {
    print path
    r = dump(path, dst "/" dumps[path], levels)
    if(r)
      errors[++error] = "dump " path " " dumps[path] " > " r
    else
      results[++result] = "dump " path " " dumps[path]
  }
  # syncs
  print "Synchronisiere Verzeichnisse:"
  for(path in syncs) {
    print path
    if(system("rsync -av " path " " dst))
      errors[++error] = "sync " path " > Synchronisation abgebrochen."
    else
      results[++result] = "sync " path
  }
  # Statusbericht ausgeben
  print "\n\n>> Backup " getDate("%Y-%m-%d %H:%M:%S") " <<"
  print "Zielverzeichnis: " dst
  if(result > 0) {
    print "\nFolgende Aktionen wurden erfolgreich ausgeführt:"
    for(i = 1; i <= length(results); i++) print "  " results[i]
  } else {
    print "\nEs wurden keine Aktionen erfolgreich ausgeführt."
  }
  if(error > 0) {
    print "\nFolgende Aktionen sind fehlgeschlagen:"
    for(i = 1; i <= length(errors); i++)  print "  " errors[i]
  }
}

# Sichert eine Partition, abhängig von den übergebenen Leveln.
function dump(path, dst, levels) {
  # Name der letzten dump Datei holen
  lscmd = "ls -r " dst "*"
  lscmd | getline ls
  close lscmd
  # Levelnummer der letzten Datei holen und neue Nummer setzen
  l = split(ls, a, "_");
  n = a[l] + 1
  if(n > length(levels)) n = 1
  # dump ausführen
  if(system("dump -" levels[n] " -Lauf " dst "_" getDate("%Y%m%d%H%M%S") "_" levels[n] "_" n " " path))
    return "Sicherung fehlgeschlagen!"
  # wenn erstes Dump, dann alle anderen löschen
  if(n == 1)
    for(i = 2; i <= length(levels); i++)
      if(system("rm -f " dst "*_" levels[i] "_" i))
        r = r "Sicherung \"" ls "\" konnte nicht gelöscht werden.\n"
  return r
}

# Gibt die akteulle Zeit im gewünschten Format zurück.
function getDate(format) {
  datecmd = "date +'" format "'"
  datecmd | getline date
  close datecmd
  return date
}
 

Anhänge

  • backup.zip
    1,5 KB · Aufrufe: 282
dagnu schrieb:
Bisher habe ich leider noch keine Idee, wie ich das Skript beim
Herunterfahren anwerfen kann (stfw - ich weis...).
Über den rc-Mechanismus:
Code:
test "$1" = "stop" && backup.awk < backup.conf
Und so machen wir das N I C H T . Baue dir entweder einen Wrapper, den du zum Shutdown aufrufst, und der dann erst den Backup- und dann den shutdown-Befehl ausführt, oder starte das Backup beim Booten (ebenfalls über den rc-Mechanismus, dann aber auf "$1" = "start" prüfen).
 
Und so machen wir das N I C H T . Baue dir entweder einen Wrapper, den du zum Shutdown aufrufst, und der dann erst den Backup- und dann den shutdown-Befehl ausführt, oder starte das Backup beim Booten (ebenfalls über den rc-Mechanismus, dann aber auf "$1" = "start" prüfen).
Stimme ich voll und ganz zu!

(ähnlich wie im Wiki, nur ohne cron, da
mein Rechenknecht nicht jede Nacht durchrennt)
Wieso nimmst Du nicht anacron, wie in der Wiki-Backup-Anleitung vorgeschlagen?
http://wiki.bsdforen.de/index.php/FreeBSD_-_Backup#Anacron
http://wiki.bsdforen.de/index.php/FreeBSD_-_Periodische_Aufgaben#anacron
 
AndreasMeyer schrieb:
Stimme ich voll und ganz zu!
Das waren dann ja schon mal zwei NICHT Antworten. Mit dem Wrapper, dass ist mir
noch ein wenig unklar - meint ihr "shutdown" ersetzen? Ein rc.d Skript führt
anscheinend ja nicht zum Erfolg, da es beim shutdown nach eine gewissen Zeit
gekillt wird.

AndreasMeyer schrieb:
Wollte cron nicht verwenden, da ich eigentlich eine Sicherung nach jedem shutdown
haben möchte, und das mal mehrere Tage dauern oder auch mehrmals am Tag
vorkommen kann.
 
Nach dem Shutdown ist es wohl ohnhein ein bißchen spät dafür...

Verwende, wie gesagt, ein Wrapper-Skript, aber achte darauf, daß durch Eingabe von shutdown immer /sbin/shutdown ausgeführt wird. Denn wenn man shutdown sagt, dann will man jetzt einen Shutdown - und nicht in 10 oder 15 Minuten, wenn irgendwelche Backups gelaufen sind. Daher ist während eines Shutdowns nach 120 Sekunden sowieso für jedes rc-Skript Schicht im Schacht.
 
Eigentlich würde ich schon gern auf die Eingabe eine Kommandos verzichten, bisher
drücke ich einfach den Power Knopf und die Kiste fährt gesittet runter - nur leider
ohne Backup.
 
Zurück
Oben