Gibt es eine Möglichkeit, einen Befehl erst auszuführen, nachdem ein anderer ohne temporäre Datei ausgeführt wurde? Ich habe einen länger laufenden Befehl und einen anderen Befehl, der die Ausgabe formatiert und sie mit curl an einen HTTP-Server sendet. Wenn ich nur ausführen commandA | commandB
, commandB
wird starten curl
, eine Verbindung zum Server herstellen und Daten senden. Da dies commandA
so lange dauert, tritt beim HTTP-Server eine Zeitüberschreitung auf. Ich kann machen was ich willcommandA > /tmp/file && commandB </tmp/file && rm -f /tmp/file
Aus Neugier möchte ich wissen, ob es eine Möglichkeit gibt, dies ohne die temporäre Datei zu tun. Ich habe es versucht, mbuffer -m 20M -q -P 100
aber der Curl-Prozess wird noch am Anfang gestartet. Mbuffer wartet nur, bis commandA
die Daten tatsächlich gesendet wurden . (Die Daten selbst sind maximal einige hundert kb groß)
commandA && commandB
?commandA
ancommandB
, oder?Antworten:
Dies ähnelt einigen anderen Antworten. Wenn Sie das Paket "moreutils" haben, sollten Sie den
sponge
Befehl haben. VersuchenDer
sponge
Befehl ist im Grunde ein Durchgangsfilter (wiecat
), außer dass er erst mit dem Schreiben der Ausgabe beginnt, wenn er die gesamte Eingabe gelesen hat. Das heißt, es "saugt" die Daten auf und gibt sie dann frei, wenn Sie sie zusammendrücken (wie ein Schwamm). Bis zu einem gewissen Grad handelt es sich also um „Betrug“. Wenn eine nicht triviale Datenmenge vorhanden ist, wird mitsponge
ziemlicher Sicherheit eine temporäre Datei verwendet. Aber es ist für dich unsichtbar; Sie müssen sich nicht um die Haushaltsführung kümmern, z. B. um die Auswahl eines eindeutigen Dateinamens und die anschließende Bereinigung.Der
{ IFS= read -r x; { printf "%s\n" "$x"; cat; } | commandB; }
liest die erste Ausgabezeile vonsponge
. Denken Sie daran, dass dies erst angezeigt wird, wenncommandA
es abgeschlossen ist. Dann wird es gestartetcommandB
, schreibt die erste Zeile in die Pipe und ruftcat
auf, um den Rest der Ausgabe zu lesen und in die Pipe zu schreiben.quelle
sponge
gleiche, wofür ich verwendet habembuffer
, scheint hier aber besser geeignet zu sein. Lesen ist hier klug. Ich werde mich auf jeden Fall für die Zukunft daran erinnern.mbuffer
; es könnte tatsächlich genauso gut sein wiesponge
. Ich bin damit einverstanden, dass die Verwendungread
ein kluger Trick ist. Ich kann es nicht voll anerkennen; Es wird von Zeit zu Zeit in Antworten in Stack Exchange (U & L, Super User, Ask Ubuntu usw.) angezeigt. Tatsächlich ist Roaimas Antwort auf diese Frage meiner sehr ähnlich, außer dass sie nicht verwendet wirdsponge
(oder etwas Äquivalentes). Wie ich in einem Kommentar erwähnt habe, verzögert sie den Start nichtcommandB
so sehr, wie Sie es benötigen (nach meinem Verständnis von Ihr Problem).Befehle in der Pipeline werden gleichzeitig gestartet. Sie müssen die
commandA
Ausgabe an einem Ort speichern , um sie später verwenden zu können. Sie können temporäre Dateien vermeiden, indem Sie die Variable verwenden:quelle
echo A
Substitution im Prozess?Ich kenne kein Standard-UNIX-Dienstprogramm, das dieses Problem beheben kann. Eine Möglichkeit wäre die Verwendung sein
awk
zu akkumulierencommandA
Ausgang und spülen Sie escommandB
bei einem Schuss, wie soBeachten Sie, dass dies speicherintensiv sein kann, da
awk
aus seiner Eingabe eine Zeichenfolge aufgebaut wird.quelle
\n
oder andereORS
.Sie können die Anforderung mit einem kleinen Skript lösen. Diese spezielle Variante vermeidet die temporäre Datei und potenzielle Speicherprobleme auf Kosten zusätzlicher Prozesse.
Wenn Sie das Skript aufrufen
waituntil
(und es ausführbar machen, in dasPATH
usw. einfügen), würden Sie es so verwendenBeispiel
quelle
commandB
biscommandA
geschrieben hat seine erste Linie der Ausgabe . Das ist wahrscheinlich nicht gut genug.sponge
. Jetzt können Sie sich darüber informieren.