ubuntuusers.de

Exitcode von Befehl in Pipe

Status: Gelöst | Ubuntu-Version: Ubuntu MATE 24.04 (Noble Numbat)
Antworten |

CarstenHa

Avatar von CarstenHa

Anmeldungsdatum:
1. Mai 2020

Beiträge: 180

Hallo liebes Forum,

ich habe folgendes Bash Konstrukt:

1
2
3
{
 Mehrere Befehle
} | befehlx | tee file

Kann ich eigentlich den Exitcode ($?) von befehlx abfangen, oder geht das in diesem Beispiel mit den beiden Pipes nicht? Ich habe für mein Programm schon indirekt eine Lösung gefunden, aber die Frage beschäftigt mich trotzdem.

Gruß

Carsten

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13370

Standardmäßig bekommt man nur den letzten Exit-Code. Aber die bash hat da auch noch eine andere Lösung:

The return status of a pipeline is the exit status of the last command, unless the pipefail option is enabled.
If pipefail is enabled, the pipeline's return status is the value of the last (rightmost) command to exit with
a  non-zero  status,  or zero if all commands exit successfully.  If the reserved word !  precedes a pipeline,
the exit status of that pipeline is the logical negation of the exit status as  described  above.   The  shell
waits for all commands in the pipeline to terminate before returning a value.

Aus der Manpage.

CarstenHa

(Themenstarter)
Avatar von CarstenHa

Anmeldungsdatum:
1. Mai 2020

Beiträge: 180

1
set -o pipefail

Super, das hilft mir weiter ☺ Danke Dir!

shiro Team-Icon

Supporter

Anmeldungsdatum:
20. Juli 2020

Beiträge: 1466

Kann ich eigentlich den Exitcode ($?) von befehlx abfangen, ...

Ja, verwende das bash Array PIPESTATUS ($ man bash | grep -A 3 PIPESTATUS).

CarstenHa

(Themenstarter)
Avatar von CarstenHa

Anmeldungsdatum:
1. Mai 2020

Beiträge: 180

Und den Exitcode von einem "Nicht-letzten"-Befehl in der Gruppierung kann ich dann wahrscheinlisch nur so in der Art abfangen, oder?

1
2
3
4
5
6
efile="$(mktemp)"
{
 cmd1
 echo "$?" >"$efile"
 cmd2
} | cmd3 | tee ./file.txt

Vielen Dank Euch beiden. Das war sehr hilf- und lehrreich.

shiro Team-Icon

Supporter

Anmeldungsdatum:
20. Juli 2020

Beiträge: 1466

Und den Exitcode von einem "Nicht-letzten"-Befehl in der Gruppierung kann ich dann wahrscheinlisch nur so in der Art abfangen, oder?

Ich hatte doch zuvor das bash Array PIPESTATUS erwähnt. Im folgendem Beispiel:

$ rm *.xxx 2>/dev/null
$ ls -log *.xxx 2>&1 | wc -w | cat -n -;  echo ${#PIPESTATUS[@]}, ${PIPESTATUS[@]};
     1	11
3, 2 0 0
$ 

ist der "ls" Befehl nicht erfolgreich (Status=2). Das die Fehlermeldung durch "2>&1" per Pipe an den Befehl "wc -w" geschickt und per pipe an den "cat" Befehl weiter geleitet wird, erhält man ein Array mit 3 Elementen ${#PIPESTATUS[@]} . Die Status-Werte der 3 Befehlen sind 2 (Fehler bei "ls") und zwei erfolgreiche Befehle ("wc" und "cat").

Interessant ist der Fehler 141 (=128+13), wenn der Wert in der Pipe wegen eines Fehlers im empfangenden Befehl nicht weiter verarbeitet werden kann. Beispiel:

$ ls -log *.xxx 2>&1 | wc -w | cat -x -;  echo ${#PIPESTATUS[@]}, ${PIPESTATUS[@]};
cat: Ungültige Option -- x
„cat --help“ liefert weitere Informationen.
3, 2 141 1
$

Natürlich liefert der letzte Befehl "cat" dann einen Status von 1.

Antworten |