2015-07-24 13 views
5

Ich versuche, einige Informationen vor jeder Zeile Ausgabe aus einer Datei hinzufügen, von:Proxy stdout/stderr zu halten, um in bash

  • sowohl stdout und stderr fing
  • vorangestellte Informationen

Hier ist mein Testskript auf den ursprünglichen Griff ausgibt:

#!/bin/bash 
# 
# Test proxying stdout and stderr 
# 

function proxy-stdouterr() { 
    local name="$1" 
    local handle=$2 
    while IFS='' read -r line 
    do 
     echo -e "[ ${name}: ${line} ]" >&${handle} 
    done 
} 

# Output some messages and attempt to parse them 
(
    echo "1: Normal message" 
    echo "2: Error" >&2 
    echo "3: Normal message" 
    echo "4: Error" >&2 
) 2> >(proxy-stdouterr "stderr" 2) > >(proxy-stdouterr "stdout" 1) 

Das funktioniert ziemlich gut, behält aber die Reihenfolge im Terminal nicht bei (Ubuntu 12.04).

Wenn nicht Proxying Ausgänge:

1: Normal message 
2: Error 
3: Normal message 
4: Error 

jedoch, wenn Proxying die Reihenfolge nicht eingehalten wird. Schlimmer noch ist dies nicht deterministisch, es die meiste Zeit ist:

[ stderr: 2: Error ] 
[ stderr: 4: Error ] 
[ stdout: 1: Normal message ] 
[ stdout: 3: Normal message ] 

Aber gelegentlich:

[ stderr: 2: Error ] 
[ stdout: 1: Normal message ] 
[ stderr: 4: Error ] 
[ stdout: 3: Normal message ] 

Wie kann ich dieses Problem beheben?

Dank

+0

Ich denke, dies ist ein grundlegendes Synchronisationsproblem: Wenn Sie Produzenten parallel zu einer freigegebenen Ressource schreiben müssen, können Sie nicht die Reihenfolge garantieren, in der diese Schreibvorgänge ohne irgendeine Form der Koordination stattfinden. – larsks

+2

Auch +1 für ein Beispiel, das die Frage eindeutig zeigt! – larsks

+0

larsks ist korrekt. Die Ausgabe wird in zwei separate IO-Streams aufgeteilt: STDOUT und STDERR (die "Producer"), die dann "proxied", vorangestellt und dann zur Konsole zurückgemeldet werden. Die Zeit für die Verarbeitung jedes Streams kann variieren, insbesondere wenn eine Bash-Funktion als Teil des Streams verwendet wird. Daher ist es nicht möglich, ihre Ausgabe zu synchronisieren (ohne irgendeine Art von Signal zu verwenden). – aks

Antwort

1

Wie andere bereits erwähnt, ist dies ein Synchronisationsproblem ohne offensichtliche Antwort ohne mehr zu wissen, welche Teile Sie gezielt steuern und ändern wollen.

IMHO Es gibt zwei Hauptoberflächen des Angriffs:

  • Strom Pufferung. Die meisten von C abgeleiteten Programme puffern stderr nicht, Puffer stdin und stdout für Zeile, wenn sie ein Terminal und Puffer sie sonst völlig sind. Dies erklärt, warum stderr in Ihrem Beispiel immer zuerst auftaucht. Ein billiger Cop-Out ist /usr/bin/echo anstelle von echo zu verwenden, so dass Sie einen flushed Stream am Ende jeder Zeile (und eine Menge Verzögerung für Prozesslaichen) bekommen. Es löst Ihr Beispiel 100% für das, was ich versucht habe, so könnte es für Sie auch genug sein. Wenn Sie die Kontrolle über den Befehl haben, der die Zeilen generiert, stellen Sie sicher, dass sowohl stdout als auch stderr in der Zeile gepuffert sind ( ).

  • Prozessterminierung. Sie haben zwei Prozesse im Wettbewerb um beide Ströme von zu lesen. Sollten beide Daten gleichzeitig fließen, sind sie in einem Rennen gegeneinander, . Sie können mildern, dass durch einen einzigen Prozess mit tun, aber ich bin nicht sicher, ob es möglich ist, zu halten sie effizient in nativer bash (keine programmierbare POSIX select zur Verfügung, die End-User)

In in jedem Fall, wenn irgendwo auf dem Bild Schlange steht, sind Sie geschraubt, soweit die Reihenfolge geht.

Verwandte Themen