1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen
  2. Unsere jährliche Weihnachts-Banner-Aktion hat begonnen! Wir freuen uns auf viele, viele kreative Vorschläge.
    Mehr dazu könnt Ihr hier nachlesen: Weihnachtsbanner 2016

    Information ausblenden

rsync und Leerzeichen

Dieses Thema im Forum "Unix & Terminal" wurde erstellt von Atelis, 25.05.07.

  1. Atelis

    Atelis Akerö

    Dabei seit:
    01.03.07
    Beiträge:
    1.831
    habe folgendes skript und 2 probleme:

    Code:
    zahlen[${#zahlen[*]}]="~/Ordner"
    zahlen[${#zahlen[*]}]="~/Ordner 2"
    zahlen[${#zahlen[*]}]="~/Ordner 3"
    echo ${zahlen[@]}
    echo
    for i in ${zahlen[@]}
    do
      echo
      echo "Backup von \""$i"\" erstellen..."
      echo "--------------------------------"
      rsync -avpt --stats --delete $i "/Volumes/LaCie 160 HD/Backup-Ordner/"
    done
    1. rsync trennt den einzelnen ordner beim leerzeichen (er sucht nach einem "ordner" und dann nach "2")
    2. aus "~/Ordner" wird "/Users/atelis/~/Ordner" - warum?
     
  2. stk

    stk Grünapfel

    Dabei seit:
    05.01.04
    Beiträge:
    7.141
    Moin,

    weil Du Leer- und Sonderzeichen mit vorangestelltem \ maskieren mußt. Aus einem einfachen Leerzeichen wird: "\ "

    Gruß Stefan
     
  3. Atelis

    Atelis Akerö

    Dabei seit:
    01.03.07
    Beiträge:
    1.831
    nein, kommt das gleiche bei raus...

    es hat irgendwas mit dem setzen der variablen zu tun: egal ob
    Code:
    i=/Users/atelis/Neuer\ Testordner
    oder
    Code:
    i="/Users/atelis/Neuer Testordner"
    der befehl
    Code:
    rsync -avpt --stats --delete $i "/Volumes/LaCie 160 HD/Backup-Ordner/"
    trennt am leerzeichen... :( es kommt immer diese fehlermeldung:
    Code:
    building file list ... rsync: link_stat "/Users/atelis/Neuer" failed: No such file or directory (2)
    rsync: link_stat "/Users/atelis/Testordner" failed: No such file or directory (2)
    done
     
  4. Rastafari

    Rastafari Golden Noble

    Dabei seit:
    10.03.05
    Beiträge:
    17.896
    Code:
    # der befehl...
    rsync -avpt --stats --delete $i "/Volumes/LaCie 160 HD/Backup-Ordner/"
    # ...trennt am leerzeichen...
    Aber der Befehl...
    Code:
    rsync -avpt --stats --delete [COLOR="Blue"]"[/COLOR]$i[COLOR="Blue"]"[/COLOR] "/Volumes/LaCie 160 HD/Backup-Ordner/"
    ...tut das nicht.
     
  5. pepi

    pepi Cellini

    Dabei seit:
    03.09.05
    Beiträge:
    8.741
    Dann schreib "$i" in Dein rsync Statement.

    Was soll das ganze Ding eigentlich tun und wie sieht der Rest aus? Reine Neugierde weil ich Serverbackups mit meinem eigenen Rsync basierten Skript erledige und immer gerne neuen Input dazu habe.
    Gruß Pepi

    Hätte ich vorm Posten doch nochmal reloaden sollen... Rastafari war schneller :)
     
  6. Atelis

    Atelis Akerö

    Dabei seit:
    01.03.07
    Beiträge:
    1.831
    danke! die anführungsstriche waren es... ;) und wen es interessiert - hier mein script (gibt mit sicherheit noch verbesserungsmöglichkeiten):

    Code:
    ######################################################################################
    ########                                                                      ########
    ####                                     Backup                                   ####
    ########                                                                      ########
    ######################################################################################
    
    Sichere_Ordner ()
    {
      quelle[${#quelle[*]}]=$1
      ziel[${#ziel[*]}]=$2
    }
    
    Zeit ()
    {
      sekunden=$(($2 - $1))
      echo $sekunden
    }
    
    ######################################################################################
    
    
    # Zu sichernde Ordner ---------------------------------------------------------------
    Sichere_Ordner $HOME"/Documents" "/Volumes/LaCie 160 HD/Backup-Ordner/"
    Sichere_Ordner $HOME"/Pictures" "/Volumes/LaCie 160 HD/Backup-Ordner/"
    Sichere_Ordner $HOME"/Movies" "/Volumes/LaCie 160 HD/Backup-Ordner/"
    Sichere_Ordner $HOME"/Music" "/Volumes/LaCie 160 HD/Backup-Ordner/"
    Sichere_Ordner $HOME"/Projekte" "/Volumes/LaCie 160 HD/Backup-Ordner/"
    Sichere_Ordner $HOME"/Library/" "/Volumes/LaCie 160 HD/Backup-Ordner/Private Library/"
    Sichere_Ordner "/Library/" "/Volumes/LaCie 160 HD/Backup-Ordner/Globale Library/"
    Sichere_Ordner "/Volumes/Windows HD/Dokumente und Einstellungen/Jakob" "/Volumes/LaCie 160 HD/Backup-Ordner/Windows HD/"
    Sichere_Ordner "/Volumes/Windows HD/Dokumente und Einstellungen/All Users" "/Volumes/LaCie 160 HD/Backup-Ordner/Windows HD/"
    
    
    
    ######################################################################################
    
    cd /
    clear
    
    if [ -d '/Volumes/LaCie 160 HD' ]
    then
      echo
      timestamp_start=`date +%s`
      echo "Backup am" `date +%d.%m.%Y`", um" `date +%H:%M:%S` "Uhr gestartet"
      echo "==========================================================================="
      echo
      echo "Mounten von \"Windows HD\"..."
      diskutil mount disk0s3 > /dev/null
      echo
      echo
      i=0
      while [ $i -lt ${#quelle[*]} ]
      do
        echo
        echo "Backup von \"${quelle[$i]}\" erstellen..."
        echo "---------------------------------------------------------------------------"
        rsync -avpt --stats --delete "${quelle[$i]}" "${ziel[$i]}"
        echo
        echo "---------------------------------------------------------------------------"
        echo
        echo
        echo
        i=$(($i + 1))
      done
      echo "Auswerfen von \"Windows HD\"..."
      diskutil unmount disk0s3 > /dev/null
      echo
      echo
      echo "==========================================================================="
      timestamp_stopp=`date +%s`
      echo "Backup am" `date +%d.%m.%Y`", um" `date +%H:%M:%S` "Uhr beendet"
      echo
      echo "Zeit:" `Zeit $timestamp_start $timestamp_stopp` "Sek."
      echo
      echo
    else
      echo "\"LaCie 160 HD\" ist nicht gemountet!"
      echo
      echo
    fi
    exit
    
     
    #6 Atelis, 26.05.07
    Zuletzt bearbeitet: 26.05.07
  7. pepi

    pepi Cellini

    Dabei seit:
    03.09.05
    Beiträge:
    8.741
    Verbesserungsmöglichkeiten gibt es immer…

    Ja, Verbesserungsmöglichkeiten gibt es immer. :) Ich bin inzwischen bei Build 68 meines Backup Skriptes mit dem 2. Branch... Fertig wird es wohl nie, aber immer besser.

    Sind ein paar interessante Ansätze drinnen in Deinem Skript und gehobene Bash 2 Syntax. :)

    Was mir abgeht, bzw. wo ich verbesserungspotential sehe.
    SheBang! Oder hast das nur nicht mitgepostet?

    Warum führst Du nicht eine Variabel $backup_disk ein?
    backup_disk="LaCie 160 HD"
    backup_path="Mein toller Backup Ordner"
    mount_point="/Volumes"
    backup_target="$mount_point/$backup_disk/$backup_path"

    rsync $rsync_options $backup_source $backup_target

    So kann man einfach mal die Pade oder sonstiges ändern und muß nur eine Variable ausbessern.

    Beim rsync fehlt meiner Ansicht nach die Option --extended-attributes

    Du rufst rsync nicht über einen absoluten Pad auf, so kannst Du nicht sicher sein, daß auch das von Dir gewünschte rsync verwendet wird. Wenn Du fink oder DarwinPorts oder Emerge verwendest hast Du mit Sicherheit mehrere rsyncs auf der HD. Je nach $PATH kann das auch mal schiefgehen.


    Warum schreibst Du die Quell Ordner nicht in eine Variable oder ein Array hinein und iterierst mit einer Schleife drüber? Deine anderen Schleifenkonstruktionen sind ja auch recht gut gebaut?

    Wenn ich mich recht erinnere soll man beim Ziel bei rsync keinen trailing Slash verwenden.

    Bis auf die Überprüfung ob Dein Ziel-Volume vorhanden ist (Großes plus dafür, das geht sonst böööse ins Auge wenn die HD mal fehlt) hast Du keine Fehlerüberprüfungen drinnen. Du gibst zwar aus, daß Dein Backup von Quelle-Blah fertig ist, aber schaust nicht nach ob das auch gut gegangen ist. Noch schlimmer, Du überprüfst nicht ob Du Dein Ziel-Volume erfolgreich mounten konntest sondern gehst davon aus, daß es geklappt hat. Das führt eigentlich die Überprüfung ad Absurdum.

    Ein log geht mir auch noch ab, aber das bin wohl ich. :)

    Gehe ich recht in der Annahme, daß Du Dein Skript immer manuell aufrufst?
    Gruß Pepi
     
    #7 pepi, 26.05.07
    Zuletzt bearbeitet: 26.05.07
  8. Atelis

    Atelis Akerö

    Dabei seit:
    01.03.07
    Beiträge:
    1.831
    ui, danke für deine sehr ausführliche stellungsnahme zu meinem skript - mache erste seit gestern richtig was mit bash-skripten - sonst waren es immer nur einzelne zeilen...

    was?

    habe ich jetzt auch gemacht und sieht so aus:

    Code:
    # Ziel -------------------------------------------------------------------------------
    zielordner="/Volumes/LaCie 160 HD/Backup-Ordner/"
    
    
    # Zu sichernde Ordner ----------------------------------------------------------------
    Sichere_Ordner $HOME"/Documents" "$zielordner"
    Sichere_Ordner $HOME"/Pictures" "$zielordner"
    Sichere_Ordner $HOME"/Movies" "$zielordner"
    Sichere_Ordner $HOME"/Music" "$zielordner"
    Sichere_Ordner $HOME"/Projekte" "$zielordner"
    Sichere_Ordner $HOME"/Library/" "${zielordner}Private Library/"
    Sichere_Ordner "/Library/" "${zielordner}Globale Library/"
    Sichere_Ordner "/Volumes/Windows HD/Dokumente und Einstellungen/Jakob" "${zielordner}Windows HD/"
    Sichere_Ordner "/Volumes/Windows HD/Dokumente und Einstellungen/All Users" "${zielordner}Windows HD/"
    
    # rsync Optionen ---------------------------------------------------------------------
    rsync_optionen="-avpt --stats --delete --extended-attributes"
    ich hab gelesen, dass es mit dem parameter probleme gibt, da rsync dann immer zu viele dateien kopiert - werde es aber mal ausprobieren...
    EDIT: wie ich es auch gelesen hatte: es werden jedes mal alle resourcefork dateien wieder neu kopiert... was nun? weglassen?

    meinst du ein "#!/bin/bash" am anfang? dann hab ich das jetzt...

    ich wollte erst 2-dimensionale arrays machen, habe aber nicht so schnell rausgefunden, wie das genau geht. weiß, dass es unsauber ist, aber habe dann einfach 2 arrays genommen - die elemente der einzelnen arrays gehören dann dementsprechend zusammen...

    ich habe nur gefunden, dass es egal wäre...? oder weißt du mehr?

    das liegt daran, dass ich immer fehler habe... ;) und zwar zugriffsrechte-fehler:

    sync: opendir "/Library/Logs/Console/0" failed: Permission denied (13)
    rsync: opendir "/Library/Logs/Console/502" failed: Permission denied (13)

    etc... ich will nicht mein admin-passwort eingeben müssen. wie kann ich solche fehler hinterher abfragen?

    ja, starte das skript mit dosomethingwhen, wenn dich die externe festplatte einschalte...

    mal nebenbei: wie kann ich das skript unterbrechen und den benutzer zu der eingabe von ja oder nein bringen?
     
  9. pepi

    pepi Cellini

    Dabei seit:
    03.09.05
    Beiträge:
    8.741
    Und ich dachte mir schon, daß es "zusammengestoppelt" wirkt. Als ob nicht alles aus ein und derselben Feder stammte. :) Die (()) Konstruktionen und die Schleifen passen einfach nicht zu den fehlenden Abstraktionsvariablen.
    Literaturtip: Advanced Bash-Scripting Guide

    Code:
    # Snipped [...]
    Sichere_Ordner $HOME"/Projekte" "$zielordner"
    Sichere_Ordner $HOME"/Library/" "${zielordner}Private Library/"
    Sichere_Ordner "/Library/" "${zielordner}Globale Library/"
    Sichere_Ordner "/Volumes/Windows HD/Dokumente und Einstellungen/Jakob" "${zielordner}Windows HD/"
    
    Du solltest Dich mit Dir selbst auf eine Syntax einigen. So ist das Kraut und Rüben. Einmal verwendest Du $zielordner, einmal ${zielordner}. Du solltest überall die idente Schreibweise verwenden. In dem Fall ${zielordner}. Das erleichtert im Zweielsfall ein Suchen und Ersetzen und man kann sicher sein, daß man alle erwischt. Es ist übrigens ein durchaus relevanter Unterschied zwischen /Library und /Library/. Bei letzterer Schreibweise wird im Ziel kein Ordner Library angelegt und nur dessen Inhalt gebackupped. Damit kopierst Du unter umständen die Inhalte zweier Ordner ineinander, was sie als Backup relativ wertlos macht und im blödesten Fall überschreibt einer den anderen.

    Besser als wenn garkeine Resourceforks übertragen werden und Dein Backup einige defekte oder unvollständige Dateien enthält sowie sämtliche Finder Kommentare verliert. Mit 10.4.9 sind solche Probleme zum Glück Vergangenheit, da Apple rsync wieder mal upgedatet hat.

    Ja, das ist das Shebang mit dem jedes Shell Skript eingeleitet wird.

    Was wohl hauptsächlich daran liegt, daß bash2 nur eindimensionale Arrays unterstützt und man mehrdimensionale Arrays nur mit viel Aufwand simulieren kann. Das ist definitv Advanced Shell Scripting.

    Zwei Ansätze zu diesem "Problem".
    Laß die Dinge von denen Du weist, daß Du sie nicht kopieren können wirst, bzw. die unsinnig sind einfach präventiv weg. Es ist nicht sinnvoll die Console Logs zu kopieren, ebenso wie es abartig wäre Ordner wie ~/Library/Caches zu sichern. Die brauchst Du definitiv nicht, wenn Du Dein Backup brauchst. Spar Dir daher die Zeit und den Speicherplatz. (siehe rsync excludes)
    In /Library mußt Du damit rechnen als nicht-Admin Leseprobleme zu haben. da hilft nur, entweder als admin bzw. gar als root (mit sudo) Aufrufen, oder diese Dinge weglassen.

    Der andere Ansatz wäre den Rückgabewert von rsync abzufragen. In der Variable $? steht immer der Exit Status des letzten Commands drinnen. Ist alles gut gegangen bekommst Du überlicherweise, und auch bei rsync eine 0 zurück. Somit kannst Du also festellen ob ein Fehler aufgetreten ist. Ein Problem bei rsync ist, daß ein Rückgabewert ungleich 0 nicht zwangsläufig bedeutet, daß nur dieser Fehler aufgetreten ist, sondern nur, daß dies der letzte Fehler war. Um alle Fehler zu finden müßte man den Kompletten Output von rsync in ein Log schreiben und dann dort rausparsen und bewerten. Eine Aufgabe der ich mich gerade mit meinem eigenen Skript widme. Einigermaßen Aufwändig kann ich Dir sagen.

    User Input im Terminal gibts mit read(1). Das setzt aber voraus, daß Dein Skript in einer interaktiven Shell läuft. Je nachdem wie DSW das Aufruft kann es sein, daß Du keine Möglichkeit hast als User auf die Frage zu antworten, wenn beispielsweise kein Terminal geöffnet wird.
    Einfach wäre das für Dich so zu lösen, daß Du mit DSW ein AppleSkript aufrufst in dem der User gefragt wird ob er nun Backuppen möchte und wenn er ja sagt, dann aus AppleSkript heraus das ShellSkript aufrufen.
    Gruß Pepi
     
  10. Atelis

    Atelis Akerö

    Dabei seit:
    01.03.07
    Beiträge:
    1.831
    ich weiß und es ist in diesem fall absicht, da es sonst 2 ordner mit dem namen library gegeben hätte...

    welches problem gibt es nicht mehr? er kopiert immernoch jedes mal alles...

    das wird schon gemacht :-D ich wollte nur einbauen, dass der benutzer mit "j" und "n" order "y" und "n" auf einige fragen antworten kann, die das abbrechen nach fehler angehen... werde mir den read-befehl mal ansehen und ein bisschen googlen...
     
  11. pepi

    pepi Cellini

    Dabei seit:
    03.09.05
    Beiträge:
    8.741
    Was hältst Du von Unterordnern für Deine Backups? Also unterschiedliche Zielordner für Deine Quellen? Wobei ich immer noch nicht verstehe warum Du nicht gleich Dein ganzes $HOME ins Backup aufnimmst, aber Du magst Deine Gründe dafür haben.

    Zu rsync sei der Artikel The State of rsync on Tiger empfohlen, auch wenn er Dich und mich nicht wirklich glücklich machen wird.

    Zu read(1) gibts natürlich wie immer eine man page und auch im bereits verlinkten Bash Scripting Guide ist User Input ein Kapitel gewidmet.
    Gruß Pepi
     
  12. Atelis

    Atelis Akerö

    Dabei seit:
    01.03.07
    Beiträge:
    1.831
    hab ich doch gemacht? die beiden ordner von der "windows hd" kommen in einen entsprechenden ordner und die dateien der beiden library-ordner werden in einen andersnamigen ordner kopiert...

    den befehl "read" hab ich schon gefunden und auch eingebaut - er behandelt den fall, dass die rechtereparatur mal scheintern sollte und fragt ab, ob das backup trotzdem gemacht werden soll...
     
  13. Atelis

    Atelis Akerö

    Dabei seit:
    01.03.07
    Beiträge:
    1.831
    ein problem habe ich noch: will die exclude-parameter in eine variable schreiben und dann in den rsync-befehl einfügen...
    sind die " den ' übergeordnet, oder wie ist das hier? folgendes funktioniert nämlich nicht:

    Code:
    "--exclude='Startmen?' --exclude='Eigene Dateien/Eigene Bilder/Hintergr?nde'"
    und wenn ich nur " verwende, natürlich auch nicht...

    aufgerufen wird die variable dann folgendermaßen:

    Code:
    rsync $rsync_optionen $ignorieren "${quelle[$i]}" "${ziel[$i]}"
    wie mache ich das?
     
  14. pepi

    pepi Cellini

    Dabei seit:
    03.09.05
    Beiträge:
    8.741
    Single Quote sind stärker als Double Quotes. Innerhalb von Single Quotes gibt es keine Variablen Expansion, innert Double Quotes schon. Wenn Du das aber nicht brauchst, kannst Du grundsätzlich schachteln wie Du möchtest.

    Viel besser wäre es wenn Du all Deine Excludes in eine eigene Datei tust und nur noch diese einbindest. So kannst Du ein neu gefundenes Exclude einfach dort eintragen und mußt nicht den Code Deines Skriptes verändern und Du kannst diese Datei auch kommentieren, damit Du später auch noch weist was und warum Du diese Datei ausnimmst.

    Code:
    ignorieren="--exclude-from=/pfad/zu/meiner/Datei/mit/den/exclusions"
    Gruß Pepi
     
  15. Atelis

    Atelis Akerö

    Dabei seit:
    01.03.07
    Beiträge:
    1.831
    ja, aber jetzt habe ich das gleiche problem, wenn in dem pfad leerzeichen vorkommen... wie sähe das dann aus?

    gib mal bitte ein beispiel - stehe da auf dem schlauch... o_O
     
  16. pepi

    pepi Cellini

    Dabei seit:
    03.09.05
    Beiträge:
    8.741
    Gewöhn Dir doch Pfade mit Leerzeichen einfach ab! :-D

    ignorieren='--exclude-from="/pfad mit nervige Leerzeichen/zu/meiner/Datei/mit/den/exclusions"'
    Gruß Pepi
     
  17. Atelis

    Atelis Akerö

    Dabei seit:
    01.03.07
    Beiträge:
    1.831
    will dich ja wirklich nicht ärgern, aber:

    Code:
    ignore='--exclude-from="/Volumes/LaCie 160 HD/Ex/Test.exclude"'
    rsync $rsync_optionen "$ignore" "${quelle[$i]}" "${ziel[$i]}"
    Code:
    rsync: failed to open exclude file "/Volumes/LaCie 160 HD/Ex/Test.exclude": No such file or directory (2)
    das verzeichnis existiert aber ganz sicher!
     
    #17 Atelis, 28.05.07
    Zuletzt bearbeitet: 28.05.07
  18. pepi

    pepi Cellini

    Dabei seit:
    03.09.05
    Beiträge:
    8.741
    Post mal ein ls -l "/Volumes/LaCie 160 HD/Ex/Test.exclude"
    Gruß Pepi
     
    Atelis gefällt das.
  19. Atelis

    Atelis Akerö

    Dabei seit:
    01.03.07
    Beiträge:
    1.831
    Code:
    -rw-r--r--   1 atelis  atelis  55 May 28 19:12 /Volumes/LaCie 160 HD/Ex/Test.exclude
     
  20. pepi

    pepi Cellini

    Dabei seit:
    03.09.05
    Beiträge:
    8.741
    Ok, dann haben wir vielleicht doch ein Schachtelungsproblem mit den Quotes.

    Bau bitte mal eine Zeile vor Deinem rsync folgendes ein und poste die Ausgabe davon.

    Code:
    echo ***
    echo rsync $rsync_optionen "$ignore" "${quelle[$i]}" "${ziel[$i]}"
    echo ***
    Die *** sind nur dazu da, damit man es leichter findet, falls Dein Skript viel Text ausgibt.
    Gruß Pepi
     

Diese Seite empfehlen