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 bash
einzige 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, cat
verwirft sie ohne Unterbrechung du
. Der Beendigungsstatus du
wird aus dem PIPESTATUS
Array 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 read
dem Beendigungsstatus beendet wird (ich weiß nicht, ob es den Befehl stoppt, wie head
es 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 read
einen 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