2012-01-12 1 views
11

Как получить правильный код возврата из приложения командной строки unix после того, как я выполнил его через другую команду, которая преуспела?Вывод команды Pipe, но сохраните код ошибки

подробно, вот ситуация:

$ tar -cEvhf - -I ${sh_tar_inputlist} | gzip -5 -c > ${sh_tar_file} -- when only the tar command fails $?=0 
$ echo $? 
0 

И то, что я хотел бы видеть это:

$ tar -cEvhf - -I ${sh_tar_inputlist} 2>${sh_tar_error_file} | gzip -5 -c > ${sh_tar_file} 
$ echo $? 
1 

Кто-нибудь знает, как это сделать?

+0

'$?' Содержит код ошибки. Вы можете сохранить его в переменной. –

+1

Мне нужно сохранить код возврата промежуточной команды, а не последнюю команду. – SamiBOB

ответ

3

Вот общее решение, использующее только оболочку POSIX и нет временных файлов:

Начиная с трубопровода: foo | бар | Баз

exec 4>&1 
error_statuses=`((foo || echo "0:$?" >&3) | 
     (bar || echo "1:$?" >&3) | 
     (baz || echo "2:$?" >&3)) 3>&1 >&4` 
exec 4>&- 

$ error_statuses содержит коды состояния неисправности любого процесса, в случайном порядке, с индексами, чтобы сказать, какая команда излучается каждый статус.

# if "bar" failed, output its status: 
echo $error_statuses | grep '1:' | cut -d: -f2 

# test if all commands succeeded: 
test -z "$error_statuses" 

# test if the last command succeeded: 
echo $error_statuses | grep '2:' >/dev/null 
4

Посмотрите на $PIPESTATUS, являющийся статусом выхода матрицы, имеющим статус выхода. Таким образом, ${PIPESTATUS[0]} имеет статус выхода первой команды в трубе, ${PIPESTATUS[1]} статус выхода второй команды и т. Д.

Например:

$ tar -cEvhf - -I ${sh_tar_inputlist} | gzip -5 -c > ${sh_tar_file} 
$ echo ${PIPESTATUS[0]} 

Чтобы распечатать все статусы использовать:

$ echo ${PIPESTATUS[@]} 
+1

Thx, но я не использую bash с моими скриптами. Я работаю с #!/Bin/sh – SamiBOB

+0

@dogbane, любая разница между '$ {PIPESTATUS [*]}' и '$ {PIPESTATUS [@]}'? Я всегда использую бывший ... – fge

+2

Вниз, $ PIPESTATUS ** НЕ СУЩЕСТВУЕТ ** в POSIX. –

10

Используйте ${PIPESTATUS[0]}, чтобы получить статус завершения первой команды в трубопроводе.

Для получения дополнительной информации см http://tldp.org/LDP/abs/html/internalvariables.html#PIPESTATUSREF

Смотрите также http://cfajohnson.com/shell/cus-faq-2.html другие подходы, если ваша оболочка не поддерживает $PIPESTATUS.

+2

Вниз, $ PIPESTATUS ** НЕ СУЩЕСТВУЕТ ** в POSIX. –

1

Как указывали другие, некоторые современные снаряды обеспечивают ТИПЕСТАТУЮ, чтобы получить эту информацию. В классическом ш, это немного сложнее, и вы должны использовать ФИФО:

 
#!/bin/sh 

trap 'rm -rf $TMPDIR' 0 
TMPDIR=$(mktemp -d) 
mkfifo ${FIFO=$TMPDIR/fifo} 

cmd1 > $FIFO & 
cmd2 < $FIFO 
wait $! 
echo The return value of cmd1 is $? 

(Ну, вам не нужно использовать ФИФО Вы можете иметь команды в начале трубы эхо статус. переменная и eval, которая в основной оболочке перенаправляет дескрипторы файлов по всему месту и в основном изгибается назад, чтобы проверять вещи, но использование fifo намного проще.)

+0

Здравствуйте, я пробовал эту технику, но не работает: я тестировал:/usr/bin/tar -cMEvhf - -I/tmp/test.tmp> $ FIFO & gzip -5 -c < $FIFO > /tmp/test.bkz wait $! echo Возвращаемое значение cmd1 равно $? – SamiBOB

+0

Какая ошибка у вас возникла? –

+0

, даже когда cmd1 терпит неудачу, $? = 0 – SamiBOB

 Смежные вопросы

  • Нет связанных вопросов^_^