Получить код выхода из подоболочки через каналы

Как я могу получить код выхода wget из процесса подоболочки?

Итак, основная проблема в том, что $? равно 0. Где может быть основано $?=8?

$> OUT=$( wget -q "http://budueba.com/net" | tee -a "file.txt" ); echo "$?"
0

На самом деле работает без tee.

$> OUT=$( wget -q "http://budueba.com/net" ); echo "$?"
8

Но массив ${PIPESTATUS} (я не уверен, что это связано с этим случаем) также не содержит этого значения.

$> OUT=$( wget -q "http://budueba.com/net" | tee -a "file.txt" ); echo "${PIPESTATUS[1]}"    

$> OUT=$( wget -q "http://budueba.com/net" | tee -a "file.txt" ); echo "${PIPESTATUS[0]}"
0

$> OUT=$( wget -q "http://budueba.com/net" | tee -a "file.txt" ); echo "${PIPESTATUS[-1]}"
0

Итак, мой вопрос: как я могу получить код выхода wget через tee и подоболочку?

Если это может быть полезно, моя версия bash — 4.2.20.


person ДМИТРИЙ МАЛИКОВ    schedule 14.02.2012    source источник


Ответы (3)


Используя $(), вы (эффективно) создаете подоболочку. Таким образом, экземпляр PIPESTATUS, на который вам нужно взглянуть, доступен только внутри вашей подоболочки (т. е. внутри $()), поскольку переменные среды не распространяются от дочерних процессов к родительским.

Вы можете сделать что-то вроде этого:

  OUT=$( wget -q "http://budueba.com/net" | tee -a "file.txt"; exit ${PIPESTATUS[0]} );
  echo $? # prints exit code of wget.

Вы можете добиться аналогичного поведения, используя следующее:

  OUT=$(wget -q "http://budueba.com/net")
  rc=$? # safe exit code for later
  echo "$OUT" | tee -a "file.txt"
person Christian.K    schedule 14.02.2012
comment
Но можно ли экспортировать весь массив ${PIPESTATUS} в родительскую оболочку? - person ДМИТРИЙ МАЛИКОВ; 14.02.2012
comment
export работает иначе — переменные экспортируются как среда переменные для дочерних процессов (от родителя). - person Christian.K; 14.02.2012
comment
Вот решение для переноса всего массива ${PIPESTATUS[@]} в родительский скрипт. Это включает в себя добавление его в конец созданной переменной, а затем перенос его в новый массив. - person Adam Katz; 02.06.2017

Остерегайтесь этого при использовании переменных local:

local OUT=$(command; exit 1)
echo $? # 0

OUT=$(command; exit 1)
echo $? # 1
person Mrskman    schedule 17.03.2017
comment
Объявление local OUT, а затем назначение OUT= в новой строке правильно устанавливает переменную кода выхода $?, если вы не хотите, чтобы область действия расширялась. - person William George; 05.04.2017

Сначала скопируйте массив PIPESTATUS. Любые чтения разрушают текущее состояние.

declare -a PSA  
cmd1 | cmd2 | cmd3  
PSA=( "${PIPESTATUS[@]}" )

Я использовал fifos для решения проблемы sub-shell/PIPESTATUS. См. bash pipestatus в команде с обратной галочкой?
Я также нашел это полезным: сценарий bash: как сохранить возвращаемое значение первой команды в конвейере?
и https://unix.stackexchange.com/questions/14270/get-exit-status-of-process-thats-передано-к-другому/70675#70675

person maxdev137    schedule 02.11.2013