So kürzen Sie die Bash-Variablenzuweisung, ohne die Pipe zu schließen

So kürzen Sie die Bash-Variablenzuweisung, ohne die Pipe zu schließen

Ich suche nach einer Möglichkeit, die Datenmenge zu begrenzen, die in einer Bash-Variable gespeichert ist, die aus der Ausgabe eines Unterprozesses initialisiert wird.

Das Problem bei dieser möglichen Lösung besteht darin, dass die gesamte Ausgabe gespeichert wird, bevor sie gekürzt wird.

#!/bin/bash

COMMAND_TO_RUN="du /"

OUT_DATA=$($COMMAND_TO_RUN)
OUT_RESULT=$?

if [[ $OUT_RESULT -ne 0 ]]; then
    echo "${OUT_DATA:0:10000}" | head mail -s "Command failed" [email protected]
fi

Alternativ OUT_DATA=$($COMMAND_TO_RUN | head -c 10000)wird der Befehl abgebrochen, wenn die ersten 10 KB der Ausgabe gelesen sind und ich den Befehl vollständig ausführen muss, um seinen Beendigungsstatus zu erfassen.

Ich kann das ganz einfach in machen python, hoffe aber auf eine basheinzige Lösung. Und auch ohne auf das Schreiben auf die Festplatte zurückgreifen zu müssen.

Antwort1

Mit einer Funktion. Zur besseren Lesbarkeit ist im folgenden Beispiel der Befehl usw. fest codiert.

truncated_du() {
   du / | { head -c 10000; cat >/dev/null; }
   return "${PIPESTATUS[0]}"
}

out_data="$(truncated_du)"
out_result="$?"

headübergibt höchstens die gewünschte Datenmenge an stdout der Funktion. Wenn mehr Daten vorhanden sind, catverwirft sie ohne Unterbrechung du. Der Beendigungsstatus duwird aus dem PIPESTATUSArray abgerufen und von der Funktion zurückgegeben.

Hinweis: meine Variablen verwenden lower case; siehediese Antwort.


Ohne Funktion sieht die gleiche Lösung so aus:

out_data="$(
   du / | { head -c 10000; cat >/dev/null; }
   exit "${PIPESTATUS[0]}"
)"
out_result="$?"

Meiner Meinung nach ist es auf diese Weise etwas weniger lesbar.

Antwort2

Dies begrenzt die Menge, die Sie erfassen, aber ich gehe davon aus, dass es mit readdem Beendigungsstatus beendet wird (ich weiß nicht, ob es den Befehl stoppt, wie heades der Fall wäre, weil der Beendigungsstatus nicht beachtet wird: `

IFS= read -r -d '' -n $chars_to_capture foo < <($command)

Der Befehl wird scheinbar bis zum Ende ausgeführt, Sie erhalten jedoch nicht den Beendigungsstatus des Befehls, sondern readeinen nicht hilfreichen Beendigungsstatus.

Ein Beispiel

$ IFS= read -r -d '' -n 19 foo < <(seq 50; touch somefile; exit 42); echo "exit=$?"; ls -l somefile
exit=0
-rw-r--r-- 1 glennjackman staff 0 Jul 22 22:04 somefile

Ich gehe davon aus, dass die Tatsache, dass die Datei berührt wird, bedeutet, dass der Befehl nicht unterbrochen wird, nachdem die angeforderte Anzahl von Zeichen erfasst wurde.

Vielleicht könnten Sie den Exit-Status in eine Datei in der Subshell schreiben:

IFS= read -r -d '' -n 10000 out_data < <( $command_to_run; echo $? > statusfile )
if [[ -f statusfile ]] && [[ "$(<statusfile)" != "0" ]]; then
    printf "%s\n" "$out_data" | head mail -s "Command failed" [email protected]
    rm statusfile
fi

verwandte Informationen