{"id":180,"date":"2015-08-22T18:44:55","date_gmt":"2015-08-22T18:44:55","guid":{"rendered":"http:\/\/www.henrik-gebauer.de\/blog\/?p=180"},"modified":"2015-08-22T18:44:55","modified_gmt":"2015-08-22T18:44:55","slug":"verbesserte-version-des-backup-skripts","status":"publish","type":"post","link":"https:\/\/www.henrik-gebauer.de\/blog\/2015\/08\/22\/verbesserte-version-des-backup-skripts\/","title":{"rendered":"Verbesserte Version des Backup-Skripts"},"content":{"rendered":"<p>Vor ein paar Monaten habe ich ein <a href=\"http:\/\/www.henrik-gebauer.de\/blog\/2015\/04\/25\/automatisierte-inkrementelle-backups-unter-linux\/\">Skript vorgestellt<\/a>, mit dem sich unter Linux inkrementelle Backups erstellen lassen. Das Backup habe ich auch schon ein paar Mal gebraucht, weil im Parallelbetrieb mit Windows 8.1 ein paar Daten zerst\u00f6rt wurden. Unter Windows 8.1 binde ich die \/home-Partition (Ext4-Dateisystem) mithilfe des Treibers von <a href=\"http:\/\/www.ext2fsd.com\/\">Ext2FSD<\/a> ein. Wenn Windows in den Standby-Modus versetzt wird und dann aber (versehentlich) Linux gestartet wird, kann es schnell zum Datenverlust kommen. Zum Gl\u00fcck ist aber jetzt ja immer ein Backup zur Hand. Trotzdem passe ich mittlerweile auf. Erg\u00e4nzend werde ich vielleicht mal daf\u00fcr sorgen, dass Linux das erkennt und dann gar nicht erst bootet.<\/p>\n<p>Das Backup-Skript setze ich nun t\u00e4glich ein und habe es auch nach und nach verbessert. Das Einbinden per UDEV klappte leider nicht so wie erhofft, stattdessen starte ich das Skript jeweils per Hand, aber das war es auch schon an n\u00f6tigen Handgriffen.<\/p>\n<p>Was mich noch gest\u00f6rt hat, war, dass das Umbenennen von Dateien nicht automatisch erkannt wurde. Wenn Ordner mit vielen Daten umbenannt oder verschoben habe, wurden die Daten komplett neu \u00fcbertragen, was ja nicht der Sinn eines inkrementellen Backups ist.<\/p>\n<p>Ein Skript, das dies l\u00f6st, ist <a href=\"https:\/\/github.com\/dparoli\/hrsync\/blob\/master\/hrsync\">hrsync<\/a> von Daniele Paroli (Lizenz siehe <a href=\"https:\/\/github.com\/dparoli\/hrsync\/blob\/master\/LICENSE\">dort<\/a>): Es wird ein verstecktes &#8222;Shadow&#8220;-Verzeichnis angelegt, das Hardlinks auf alle Dateien enth\u00e4lt. Dies wird beim Backup mit \u00fcbertragen. Wenn eine Datei verschoben wird, zeigt die Shadow-Datei noch auf dieselbe Stelle im Dateisystem, sodass rsync beim Backup nur den Link aktualisieren muss. Durch diesen Trick wird auf dem Backupmedium Speicherplatz und beim Backup Zeit und \u00dcbertragungsvolumen gespart.<\/p>\n<p>Hier ist das aktualisierte Skript (inklusive der UDEV-Abschnitte, die bei mir nicht mehr aufgerufen werden):<\/p>\n<pre>#!\/bin\/bash\r\n\r\nSource=\"\/home\/henrik\"\r\nTarget=\"\/backup\"\r\nConfig=\"$Source\/.backup.conf\"\r\nShadow=\".backup.shadow\"\r\nLogfile=\"$Target\/backup.0\/backup.log\"\r\n\r\n# falls von UDEV aufgerufen\r\nif [ \"$1\" = \"udev\" ]; then\r\n\r\n\u00a0\u00a0\u00a0 # UDEV triggert mehrfach hintereinander. Die Datensicherung aber nur einmal (minimale Wartezeit 10 Minuten) ansto\u00dfen\r\n\u00a0\u00a0\u00a0 if [ -f \/tmp\/backup.lock ]; then\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 filemtime=$(stat -c %Y \/tmp\/backup.lock)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 currtime=$(date +%s)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 diff=$(($currtime-$filemtime))\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if [ $diff -lt 600 ]; then\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 exit;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 fi\r\n\u00a0\u00a0\u00a0 fi\r\n\r\n\u00a0\u00a0\u00a0 touch \/tmp\/backup.lock\r\n\r\n\u00a0\u00a0\u00a0 DISPLAY=:0 kdialog --msgbox \"Backup wird erstellt.\"\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 # Ausgabe umleiten\r\n\u00a0\u00a0\u00a0 exec 2&gt;&amp;1 &gt;&gt; \/tmp\/backup.log\r\nfi\r\n\r\necho \"Mounten des Backup-Ger\u00e4ts: $Target\"\r\nmount \"$Target\"\r\n\r\nsleep 1\r\n\r\ncd \"$Target\"\r\n\r\n# backup.$n verschieben nach backup.{$n+1}\r\ni=0\r\nwhile [ -d \"backup.$i\" ]; do\r\n\u00a0\u00a0\u00a0 i=$(($i+1))\r\ndone\r\ni=$(($i-1))\r\nwhile [ $i -gt 0 ]; do\r\n\u00a0\u00a0\u00a0 j=$(($i+1))\r\n\u00a0\u00a0\u00a0 echo \"Verschiebe backup.$i nach backup.$j\"\r\n\u00a0\u00a0\u00a0 mv \"backup.$i\" \"backup.$j\"\r\n\u00a0\u00a0\u00a0 i=$(($i-1))\r\ndone\r\n\r\n# letztes Backup kopieren mit Hardlinks -&gt; inkrementelles Backup\r\nif [ -d \"backup.0\" ]; then\r\n\u00a0\u00a0\u00a0 echo \"Kopiere backup.0 nach backup.1\"\r\n\u00a0\u00a0\u00a0 cp -al backup.0 backup.1\r\nelse\r\n\u00a0\u00a0\u00a0 mkdir backup.0\r\nfi\r\n\r\n# Datum setzen und neue Logdatei\r\ntouch backup.0 \r\n\r\nif [ -f \"$Logfile\" ]; then \r\n\u00a0\u00a0\u00a0 rm \"$Logfile\"\r\nfi\r\n\r\ncd \"$Source\"\r\n\r\n\r\n# zu sichernde Ordner aus Konfigurationsdatei lesen\r\nIFS=$'\\n'\r\ndirs=$(cat \"$Config\")\r\n\r\n# Ordner sichern\r\nfor dir in $dirs; do\r\n\u00a0\u00a0\u00a0 echo \"Erstelle Backup f\u00fcr Ordner $dir.\" | tee -a \"$Logfile\"\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 # Ordner wurde noch nie gesichert: Shadow-Ordner anlegen\r\n\u00a0\u00a0\u00a0 if [ ! -d \"$dir\/$Shadow\" ]; then\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 echo \"Erstelle Shadow-Ordner\" | tee -a \"$Logfile\"\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 rsync -a --delete --link-dest=\"..\" --exclude=\"\/$Shadow\" \"$dir\"\/ \"$dir\/$Shadow\" | tee -a \"$Logfile\"\r\n\u00a0\u00a0\u00a0 fi\r\n\r\n\u00a0\u00a0\u00a0 # synchronisieren\r\n\u00a0\u00a0\u00a0 echo \"synchronisiere\" | tee -a \"$Logfile\"\r\n\u00a0\u00a0\u00a0 rsync -axXhHv --stats --no-inc-recursive --numeric-ids --delete --delete-after \"$dir\"\/ \"$Target\/backup.0\/$dir\/\" | tee -a \"$Logfile\"\r\n\r\n\u00a0\u00a0\u00a0 status=$?\r\n\r\n\u00a0\u00a0\u00a0 if [ $status -eq 0 ]; then\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 echo \"Synchronisation abgeschlossen.\" | tee -a \"$Logfile\"\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 echo \"Quell-Shadow-Ordner aktualisieren\" | tee -a \"$Logfile\"\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 rsync -a --delete --link-dest=\"..\" --exclude=\"\/$Shadow\" \"$dir\"\/ \"$dir\/$Shadow\"\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 echo \"Ziel-Shadow-Ordner aktualisieren\" | tee -a \"$Logfile\"\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 rsync -a --delete --link-dest=\"..\" --exclude=\"\/$Shadow\" \"$Target\/backup.0\/$dir\/\" \"$Target\/backup.0\/$dir\/$Shadow\"\r\n\u00a0\u00a0\u00a0 else\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 echo \"Synchronisation ist fehlgeschlagen. (Status $status)\" | tee -a \"$Logfile\"\r\n\u00a0\u00a0\u00a0 fi\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 echo \"\" | tee -a \"$Logfile\"\r\ndone\r\n\r\necho \"Unmounten von $Target\"\r\numount \"$Target\"\r\n\r\nif [ \"$1\" = \"udev\" ]; then\r\n\u00a0\u00a0\u00a0 DISPLAY=:0 kdialog --msgbox \"Datensicherung abgeschlossen.\"\r\n\u00a0\u00a0\u00a0 echo \"Datensicherung abgeschlossen.\"\r\nfi<\/pre>\n<div class=\"twoclick_social_bookmarks_post_180 social_share_privacy clearfix 1.6.4 locale-de_DE sprite-de_DE\"><\/div><div class=\"twoclick-js\"><script type=\"text\/javascript\">\/* <![CDATA[ *\/\njQuery(document).ready(function($){if($('.twoclick_social_bookmarks_post_180')){$('.twoclick_social_bookmarks_post_180').socialSharePrivacy({\"services\":{\"facebook\":{\"status\":\"on\",\"txt_info\":\"2 Klicks f\\u00fcr mehr Datenschutz: Erst wenn Sie hier klicken, wird der Button aktiv und Sie k\\u00f6nnen Ihre Empfehlung an Facebook senden. Schon beim Aktivieren werden Daten an Dritte \\u00fcbertragen - siehe <em>i<\\\/em>.\",\"perma_option\":\"off\",\"action\":\"like\",\"language\":\"de_DE\"},\"twitter\":{\"reply_to\":\"HenrikGebauer\",\"tweet_text\":\"Verbesserte%20Version%20des%20Backup-Skripts%20%C2%BB%20Henrik\",\"status\":\"on\",\"txt_info\":\"2 Klicks f\\u00fcr mehr Datenschutz: Erst wenn Sie hier klicken, wird der Button aktiv und Sie k\\u00f6nnen Ihre Empfehlung an Twitter senden. Schon beim Aktivieren werden Daten an Dritte \\u00fcbertragen - siehe <em>i<\\\/em>.\",\"perma_option\":\"off\",\"language\":\"de\",\"referrer_track\":\"\"},\"gplus\":{\"status\":\"on\",\"txt_info\":\"2 Klicks f\\u00fcr mehr Datenschutz: Erst wenn Sie hier klicken, wird der Button aktiv und Sie k\\u00f6nnen Ihre Empfehlung an Google+ senden. Schon beim Aktivieren werden Daten an Dritte \\u00fcbertragen - siehe <em>i<\\\/em>.\",\"perma_option\":\"off\",\"referrer_track\":\"\"}},\"txt_help\":\"Wenn Sie diese Felder durch einen Klick aktivieren, werden Informationen an Facebook, Twitter, Flattr, Xing, t3n, LinkedIn, Pinterest oder Google eventuell ins Ausland \\u00fcbertragen und unter Umst\\u00e4nden auch dort gespeichert. N\\u00e4heres erfahren Sie durch einen Klick auf das <em>i<\\\/em>.\",\"settings_perma\":\"Dauerhaft aktivieren und Daten\\u00fcber-tragung zustimmen:\",\"info_link\":\"http:\\\/\\\/www.heise.de\\\/ct\\\/artikel\\\/2-Klicks-fuer-mehr-Datenschutz-1333879.html\",\"uri\":\"https:\\\/\\\/www.henrik-gebauer.de\\\/blog\\\/2015\\\/08\\\/22\\\/verbesserte-version-des-backup-skripts\\\/\",\"post_id\":180,\"post_title_referrer_track\":\"Verbesserte+Version+des+Backup-Skripts\",\"display_infobox\":\"on\"});}});\n\/* ]]> *\/<\/script><\/div>","protected":false},"excerpt":{"rendered":"<p>Vor ein paar Monaten habe ich ein Skript vorgestellt, mit dem sich unter Linux inkrementelle Backups erstellen lassen. Das Backup habe ich auch schon ein paar Mal gebraucht, weil im Parallelbetrieb mit Windows 8.1 ein paar Daten zerst\u00f6rt wurden. Unter Windows 8.1 binde ich die \/home-Partition (Ext4-Dateisystem) mithilfe des Treibers von Ext2FSD ein. Wenn Windows &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.henrik-gebauer.de\/blog\/2015\/08\/22\/verbesserte-version-des-backup-skripts\/\" class=\"more-link\"><span class=\"screen-reader-text\">\u201eVerbesserte Version des Backup-Skripts\u201c<\/span> weiterlesen<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/www.henrik-gebauer.de\/blog\/wp-json\/wp\/v2\/posts\/180"}],"collection":[{"href":"https:\/\/www.henrik-gebauer.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.henrik-gebauer.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.henrik-gebauer.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.henrik-gebauer.de\/blog\/wp-json\/wp\/v2\/comments?post=180"}],"version-history":[{"count":1,"href":"https:\/\/www.henrik-gebauer.de\/blog\/wp-json\/wp\/v2\/posts\/180\/revisions"}],"predecessor-version":[{"id":181,"href":"https:\/\/www.henrik-gebauer.de\/blog\/wp-json\/wp\/v2\/posts\/180\/revisions\/181"}],"wp:attachment":[{"href":"https:\/\/www.henrik-gebauer.de\/blog\/wp-json\/wp\/v2\/media?parent=180"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.henrik-gebauer.de\/blog\/wp-json\/wp\/v2\/categories?post=180"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.henrik-gebauer.de\/blog\/wp-json\/wp\/v2\/tags?post=180"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}