Вывод команды трубопровода в тройник, но также сохранение кода выхода команды

У меня есть оболочка script, в которой я завершаю команду (mvn clean install), чтобы перенаправить вывод в файл журнала.

#!/bin/bash
...
mvn clean install [email protected] | tee $logfile
echo $? # Does not show the return code of mvn clean install

Теперь, если mvn clean install выходит из строя с ошибкой, я хочу, чтобы моя оболочка-оболочка script также завершилась с ошибкой. Но так как я собираю все выходные данные в tee, я не могу получить код возврата mvn clean install, поэтому, когда я получаю доступ к $? после этого, он всегда равен 0 (с тех пор, как он достигает успеха).

Я попробовал позволить команде записать вывод ошибки в отдельный файл и проверить это потом, но вывод ошибки mvn всегда пуст (кажется, что он только записывает на stdout).

Как сохранить код возврата mvn clean install, но все же передать вывод в файл журнала?

Ответ 1

Поскольку вы используете bash, вы можете использовать $PIPESTATUS вместо $?:

mvn clean install [email protected] | tee $logfile
echo ${PIPESTATUS[0]}

Ответ 2

Вы можете установить опцию pipefail shell option для получения желаемого поведения.

Из справочного руководства Bash:

Состояние выхода конвейера - это статус выхода последней команды в конвейере, если параметр pipefail не включен (см. The Set Builtin). Если параметр pipefail включен, статус возврата конвейера является значение последней (самой правой) команды для выхода с ненулевым статусом, или ноль, если все команды успешно завершены.

Пример:

$ false | tee /dev/null ; echo $?
0
$ set -o pipefail
$ false | tee /dev/null ; echo $?
1

Чтобы восстановить исходный параметр трубы:

$ set +o pipefail

Ответ 3

Вы можете запустить команду mvn и кешировать код выхода... Я использую команду "false" для моего примера.

$ { false ; echo $? > /tmp/false.status ; } | tee $logfile
$ cat /tmp/false.status
1

Таким образом вы можете использовать содержимое файла состояния для принятия дальнейших решений.

Мне любопытно, есть ли еще более красноречивый способ выполнить это.

Ответ 4

Обходной путь (примечание: решение perfer @Frederic):

f=`mktemp`
(mvn clean install [email protected]; echo $?>$f) | tee $logfile
e=`cat $f` #error in variable e
rm $f