Правильно ли использовать «exit $ {?}» В bash? - PullRequest
2 голосов
/ 11 марта 2020

Допустим, я кодирую что-то вроде:

if [ ${?} -ne 0 ]; then 
    exit ${?}

Будет ли это работать правильно? Это правильный "синтаксис"?

Ответы [ 3 ]

5 голосов
/ 11 марта 2020

Команда [ в вашем операторе if установит $? после проверки. Вам нужно сохранить исходное состояние выхода перед тестированием.

some_command
es=$?
if [ "$es" -ne 0 ]; then
    exit "$es"
fi
3 голосов
/ 11 марта 2020

Синтаксис правильный, но $? сбрасывается командой [ ... ] в операторе if. По определению, если введен блок if, то тест [ ... ] должен быть успешным, а $? гарантированно будет 0.

. Вам нужно будет сохранить его в переменной .

result=$?
if ((result != 0)); then 
    exit "$result"
fi

С другой стороны, более логично c проверять результат команды напрямую, а не $?. Если вы это сделаете, у вас не возникнет проблем с изменением $?.

if command; then
    echo success
else
    exit   # `exit` is equivalent to `exit $?`
fi

Если вас не волнует успех, вы можете использовать ||:

command || exit
1 голос
/ 11 марта 2020

Если вы хотите выйти при ошибке и сохранить код EXIT команды, вы можете включить опцию errexit:

  • Либо с помощью: set -e
  • Либо с: set -o errexit

См .: help set | grep -F -- -e

-e Выход немедленно, если команда завершается с ненулевым статусом.

errexit аналогично -e

В качестве альтернативы вы можете trap сигнал ERR и использовать его для выхода с возвратом код ошибки.

Это избавит вас от последствий последствия опции -e.

#!/usr/bin/env bash

err_handler() {
  set -- $?
  printf 'The error handler caught code #%d\n' "$1" >&2
  exit "$1"
}

trap 'err_handler' ERR

create_error() {
  [ $# -ne 1 ] && return 0
  printf 'Create error #%d\n' "$1"
  return "$1"
}

create_error "$@"

Тестирование с различными ошибками:

for e in 1 0 2; do ./a.sh "$e" ;echo $?; done
Create error #1
The error handler caught code #1
1
Create error #0
0
Create error #2
The error handler caught code #2
2
...