2013-09-04 2 views
35

У меня обычно есть -e, установленный в моих сценариях Bash, но иногда я хотел бы запустить команду и получить возвращаемое значение.Bash получить статус выхода команды при включенном 'set -e'?

Не делая танец set +e; some-command; res=$?; set -e, как я могу это сделать?

+0

Из-за проблем, подобных этому, я бы рекомендовал НЕ использовать 'set -e' Вот еще несколько примеров: http://mywiki.wooledge.org/BashFAQ/105 – idfah

+5

Не согласен. При использовании bash для настройки систем или другой, фактической работы 'set -e' имеет важное значение для показа корректности. – phs

ответ

43

bash Из инструкции:

Оболочка не выходит, если команда, которая не является [...] часть любой команды, выполненной в & & или || список [...].

Так, просто сделать:

#!/bin/bash 

set -eu 

foo() { 
    # exit code will be 0, 1, or 2 
    return $((RANDOM % 3)) 
} 

ret=0 
foo || ret=$? 
echo "foo() exited with: $ret" 

Пример работает:

$ ./foo.sh 
foo() exited with: 1 
$ ./foo.sh 
foo() exited with: 0 
$ ./foo.sh 
foo() exited with: 2 

Это канонический способ сделать это.

+3

Возможно, вам захочется инициализировать ret = 0, прежде чем вы это сделаете, в случае успеха команды. Некоторые из них делают :) – rici

+0

@ AdrianFrühwirth - у меня был 'ret = 0' перед' foo || ret = $? ', чтобы он показал случай, когда это удалось. Я действительно тестировал его несколько раз ('for i в $ (seq 30), do echo '$ ./foo.sh'; /tmp/stack.sh; done') и скопировал некоторые результаты. –

+0

@ TheDoctorWhat Извините, я не обратил на это внимания. Я вернулся к вашему редактированию. Thanks :-) –

6

Возможно, попробуйте запустить соответствующие команды в подоболочке, например?

res=$(some-command > /dev/null; echo $?) 
-2

Используйте функцию-обертку, чтобы выполнить ваши команды:

function __e { 
    set +e 
    "[email protected]" 
    __r=$? 
    set -e 
} 

__e yourcommand arg1 arg2 

И использовать $__r вместо $?:

if [[ __r -eq 0 ]]; then 
    echo "success" 
else 
    echo "failed" 
fi 

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

function __p { 
    set +e 
    local __A=() __I 
    for ((__I = 1; __I <= $#; ++__I)); do 
     if [[ "${!__I}" == '|' ]]; then 
      __A+=('|') 
     else 
      __A+=("\"\$$__I\"") 
     fi 
    done 
    eval "${__A[@]}" 
    __r=$? 
    set -e 
} 

Пример:

__p echo abc '|' grep abc 

И я на самом деле предпочитают этот синтаксис:

__p echo abc :: grep abc 

Что я мог сделать с

... 
     if [[ ${!__I} == '::' ]]; then 
... 
+0

@DavidWolever Пожалуйста, расскажите мне, что вы думаете об этом решении. – konsolebox

+0

Это будет, например, перерыв в перенаправлении ввода-вывода. –

+0

@ AdrianFrühwirth Я сомневаюсь в этом. Пример? – konsolebox

10

в качестве альтернативного

ans=0 
some-command || ans=$? 
Смежные вопросы