Bash, Rückkehr von der umgeleiteten Schleife, ist es sicher?

7

Beachten Sie, dass wir von einer Schleife zurückkehren, die umgeleitet wird.

Ich weiß nicht, ob ich mir Gedanken über den Schreibpuffer von "Datei" machen soll.

function f {
    i=1
    while :
    do
        echo aaaaaaaaaaaaabbbbbbbbbbbbbbbbb
        ((i++))
        if [ $i -gt 3 ]
        then
            return    # return while redirected
        fi
    done >> file    # writing to file
}

f

HINWEIS: Mir ist bekannt, dass diese Funktion leicht umgeschrieben werden kann, sodass sie nicht aus der umgeleiteten Schleife zurückkehrt. Dies ist jedoch nur ein vereinfachtes Beispiel für den Zweck dieser Frage.

Versuchen Sie also bitte nicht, diesen Code zu verbessern .

Ich bin auch nicht an Problemumgehungen interessiert.

Meine einzige Frage ist, ob es etwas gibt, dessen ich mir besonders bewusst sein sollte. Wie der Dateideskriptor ist nicht richtig geschlossen. Oder manchmal kann ich erwarten, dass nur die Hälfte des Puffers (dh "aaaaaa") in die Datei geschrieben wird.

Ich würde gerne wissen, ob dies eine sehr schlechte Idee ist und warum? Oder würde es vielleicht ohne unvorhergesehene Rennbedingungen oder ähnliches funktionieren? (Aber ich möchte auch keine Antworten wie "Es ist schlecht, weil Sie stattdessen dieses und jenes Muster verwenden sollten")

Zoltan K.
quelle

Antworten:

11

Während jeder Befehl seinen eigenen Schreibpuffer haben kann, gibt es keinen Schreibpuffer, der von Befehlen gemeinsam genutzt wird, selbst wenn Bash integriert ist (oder sogar zwei Aufrufe desselben Befehls, ob integriert oder nicht).

Sogar ksh93, von dem bekannt ist, dass es eine E / A-Optimierung durchführt (zum Beispiel liest es voraus und teilt einige Daten bei der Eingabe ( was einige Fehler verursacht )), tut dies nicht.

In dieser Hinsicht ist es also sicher. Nachdem ein Befehl wie Ihr Befehl beendet wurde echo aaaaaaaaaaaaabbbbbbbbbbbbbbbbbund kein unbeaufsichtigter Prozess im Hintergrund ausgeführt wird, können Sie sicher sein, dass alle E / A-Vorgänge ausgeführt wurden.

Ein paar Anmerkungen. In einer Funktion wie:

f() {
  {
    echo x
    return
    echo y
  } > file
  echo something else
}

In der Bourne-Shell (und nur in der Bourne-Shell) returnwürde dies die Ausgabe der inneren Befehlsgruppe unterbrechen, aber nicht von der Funktion zurückkehren, wie in dieser alten Shell. Diese Befehlsgruppe würde aufgrund der Umleitung in einer Subshell ausgeführt (also Sie ' d siehe die something else).

Das passiert nicht mehr in modernen Muscheln wie bash, aber Sie hätten das gleiche Problem in Bash, wenn Sie schreiben würden:

f() {
  (
    echo x
    return
    echo y
  ) > file
  echo something else
}

oder

f() {
  {
    echo x
    return
    echo y
  } | tr xy ab
  echo something else
}

Beachten Sie, dass in einigen Fällen nicht auf einige Befehle gewartet wird. Im:

f() {
  {
    echo >(sleep 1; echo x)
    return
  } > file
}
f; cat file

Möglicherweise wird xdies nicht angezeigt, da cates zuvor ausgeführt wurde echo x.

Einige Shells (wenn auch nicht bash) haben ähnliche potenzielle Probleme mit Pipeline-Komponenten, die nicht ganz rechts sind.

Stéphane Chazelas
quelle