2012-10-26 4 views
5

Ich muss die BASH "set -o pipefail" -Option auf POSIX-Art implementieren, damit sie auf verschiedenen LINUX/UNIX-Varianten funktioniert . Um dies ein wenig zu erklären, ermöglicht diese Option dem Benutzer, die erfolgreiche Ausführung aller Piped-Befehle zu überprüfen. Mit dieser Option wurde dieser Befehl cat app.log | aktiviert grep 'ERROR' schlägt fehl, wenn 'cat' fehlschlägt, andernfalls wird der 'cat' Fehler unterdrückt.Wie man "set -o pipefail" auf POSIX-Weise implementiert - fast fertig, Expertenhilfe benötigt

So fand ich eine sehr schöne Lösung hier: http://cfaj.ca/shell/cus-faq-2.html

 run() { 
     j=1 
     while eval "\${pipestatus_$j+:} false"; do 
      unset pipestatus_$j 
      j=$(($j+1)) 
     done 
     j=1 com= k=1 l= 
     for a; do 
      if [ "x$a" = 'x|' ]; then 
      com="$com { $l "'3>&- 
         echo "pipestatus_'$j'=$?" >&3 
         } 4>&- |' 
      j=$(($j+1)) l= 
      else 
      l="$l \"\$$k\"" 
      fi 
      k=$(($k+1)) 
     done 
     com="$com $l"' 3>&- >&4 4>&- 
        echo "pipestatus_'$j'=$?"' 
     exec 4>&1 
     eval "$(exec 3>&1; eval "$com")" 
     exec 4>&- 
     j=1 
     while eval "\${pipestatus_$j+:} false"; do 
      eval "[ \$pipestatus_$j -eq 0 ]" || return 1 
      j=$(($j+1)) 
     done 
     return 0 
     } 

Die oben genannte Funktion run() ermöglicht es dem Benutzer, die verrohrt Befehle in einer solchen Art und Weise aufzurufen: laufen cmd1 \| cmd2 \| cmd3 Wenn einer der Befehle fehlschlägt Sie bekommen es in $?

Es gibt jedoch ein Problem, das die Gruppierung von Befehlen zwischen Pipes nicht unterstützt. Ich möchte in der Lage sein, so etwas aufzurufen:

run echo "test" ; grep "test" \| awk '{print}' 

Wenn ich es tue, schlägt der Aufruf fehl. Ich kann nicht die richtige Änderung erhalten, um die Gruppierung von Befehlen zu unterstützen - das Skript ist ein bisschen zu komplex für meine Bash-Fähigkeiten ... Könnte jemand helfen?

Danke!

Es gibt eine Definition eines run() Funktion, die es dem Benutzer ermöglicht, die verrohrt Befehle in einer solchen Art und Weise auszuführen:

+0

';' gruppiert keine Befehle zwischen Pipes in bash. '(...; ...)' oder '{...; ...; } 'tut. – choroba

+0

'set -o pipefail'. 'set -e' ist anders. Dies ist möglich, aber wahrscheinlich mehr Mühe als es wert ist. Ksh unterstützt auch Pipefail und mksh unterstützt 'PIPESTATUS', mit dem sich Pipefail einfach implementieren lässt. Ich würde ernsthaft in Erwägung ziehen, eine andere Sprache zu verwenden, bevor Sie dies in POSIX sh versuchen. – ormaaj

+0

@choroba - das ist was ich meinte. Du hast recht. Dies funktioniert auch nicht. –

Antwort

3

Wenn Sie Folgendes eingeben:

run echo "test" ; grep "test" \| awk '{print}' 

Sie run mit den Argumenten aufrufen echo und "test"; dann rufen Sie grep mit Argumenten "test", |, awk und {print} auf. In der Regel wird grep keine der Dateien |, awk oder {print} finden.

run aufzurufen, wie man wollte, dann würden Sie das Semikolon entkommen müssen, wie Sie den | tat (und Sie müssten die Dinge tun, in ähnlicher Weise für && oder || oder & und möglicherweise auch andere Komponenten einer Befehlszeile die Handhabung von $(...) oder Backticks `...` muss sorgfältig bedacht werden).

Wenn Sie schreiben:

run echo "test" \; grep "test" \| awk '{print}' 

Sie mindestens alle Argumente bekommen Sie run bestimmt. Ob es dann funktioniert, ist umstritten; Ich verstehe noch nicht, wie der run Code, den Sie zeigten, funktionieren soll.

[... Später ...]

es hat einige gefürchteten I/O-Umleitungen, aber hüllt jedes Segment eines durch ein Rohr Symbol in ein separates kleines Paket von Schriftzeichen getrennt Befehl. Es geht davon aus, dass das Umbrechen von Anführungszeichen um ein Argument es korrekt neutralisiert, was nicht immer der Fall ist (obwohl es oft der Fall ist).

0

Schreiben Sie Ihre eigene Shell in Standard C, oder patchen Sie die Standard Shell, oder verwenden Sie eine bestehende Shell mit etwas wie -o pipefail.

Klar -o pipefail ist eine wichtige Eigenschaft, die in der Standard-Shell sein sollte, und wenn Sie mich fragen, diese Hacks, um es in Standard-Shell zu imitieren sind hässlich und schlechter als nutzlos.