Stolperstrick in der Shell

Eigentlich fühle ich mich in Unix-Shells halbwegs zu Hause. Trotzdem gibt von Zeit zu Zeit eigentlich einfache Situationen die mich verwirren. Heute war es wieder mal so weit: ein Kollege wunderte sich dass eine Datei von einem Skript nicht kopiert wurde. Quelle sowie Ziel waren les- und beschreibbar, also alles in bester Ordnung. Allerdings gab es eine Fehlermeldung, die aber meiner Meinung die Kopie nicht verhindern sollte.

Um das mal einfach nachzustellen:

$ touch quelle log
$ chmod 444 log
$ cp quelle ziel >> log
zsh: permission denied: log

Natürlich ist das Logfile so nicht beschreibbar. Trotzdem hätte ich damit gerechnet dass die Datei kopiert würde. Wurde sie aber nicht. Weder auf AIX in der ksh, noch in anderen Shells die ich auf anderen Betriebssystemen ausprobiert habe. Hätte ich damit rechnen müssen?

6 Kommentare

  1. Wow, nett…. danke. Nein, damit hätte man nicht rechnen müssen.

    Lustigerweise klappt das hier:
    $ $(cp quelle ziel) >> log
    oder
    $ cp quelle ziel | tee log

    Gruß
    Ben

  2. Das erste ist wohl kein wirklicher Ersatz. Ich meine sobald beim Kopieren was schief geht gibt es eine merkwuerdige Fehlermeldung weil die Shell versucht die Fehlermeldung auszufuehren. Das zweite ist ein besserer Ansatz, wenn auch nicht gleichwertig. Zugegeben: mein Beispiel oben ist auch an einer entscheidenden Stelle vereinfacht, eigentlich sollte natuerlich auch bei Erfolg was im Log erscheinen. Die Loesung ist wahrscheinlich sowas wie das hier:

    cp -v quelle ziel 2>&1 | tee -a log

    Aber schoen ist anders… :-(

  3. Nun, die echte Lösung wäre wohl eher zu testen ob mal das Logfile beschreiben darf oder nicht.
    Also etwas in der Art:

    [ -e log ] && [ -w log ] &Also im Voraus für geregelte Verhältnisse sorgen. IMHO ist das für Skripte im Produktionseinsatz
    auch eine ganz gute Idee. :)

    SUSv3 sagt zu dem Zusammenhang:

    „A failure to open or create a file will cause the redirection to fail.“

    Und weiter zur Ausführung der damit zusammenhängenden Kommandos:

    „If any of the redirections performed in the current shell execution environment fail, the
    command will immediately fail with an exit status greater than zero, and the shell will
    write an error message indicating the failure.

    Von daher verhält sich deine Shell da exakt wie im Standard gefordert.

    Gruß, Frank

  4. Huch. Da wurde der Beispielcode aber vim Blog zerrissen.
    Im Übringen war auch noch ein Fehler drin…

    Also nochmal:

    if [ -e log ] && ! [ -w log ]; then
    echo ‚Cannot write to logfile `log’\“. Giving up.\n‘
    exit 1
    fi

  5. Danke Frank, das ist natuerlich der bessere Ansatz. Manchmal verliert man im Eifer des Gefechtes die gute Kinderstube aus den Augen. :-)

    Dass das so in irgendeinem Standard steht habe ich mir schon gedacht. Insbesondere nachdem verschiedene Shells (ksh, zsh, bash) das gleiche Verhalten an den Tag gelegt haben. Aber ich muss zugeben dass ich SUSv3 nicht auswendig kenne, und intuitiv haette ich hier ein anderes Verhalten erwartet. Wobei: wenn man darueber nachdenkt ist das so schon der bessere Ansatz…

  6. Huh.

    In nicht-interaktiven Shells ist das Verhalten wohl nochmal anders definiert. Wie
    unter „Consequences of Shell Errors“ beschrieben. Von der Tabelle aus würde ich
    sagen, daß „cp“ als nicht-builtin eigentlich laufen müsste (wenn es nicht selbst aussteigt
    falls sein stdout nicht schreibbar ist).

    Zsh und bash verhalten sich für mich auf den ersten Blick gerade nicht dementsprechend.

    …ich glaube ich schau mir das nach Feierabend nochmal genauer an. :-)

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

;-) :-) :-D :-| :-/ :-( :-P more »