Bash: захватывать код завершения вместо прерывания, когда задано «set -e»? - PullRequest
0 голосов
/ 19 марта 2020

По большей части я предпочитаю, чтобы мои сценарии заканчивались при возникновении непредвиденной ошибки, и поэтому обычно они запускаются с set -e -u -E -o pipefail.

Однако иногда мне нужно захватить код завершения одного вызова и не завершается. Это приводит к таким конструкциям, как

# (1) Verbose. Breaks when moved between scripts 
#              with different global -e setting.
set +e
COMMAND WITH A LOT OF ARGUMENTS \
    | AND MAYBE EVEN PIPES \
    | MAYBE OVER MANY LINES
exitCode=$?
set -e

# (2) Verbose.
if COMMAND WITH A LOT OF ARGUMENTS \
    | AND MAYBE EVEN PIPES \
    | MAYBE OVER MANY LINES
then exitCode=$?
else exitCode=$?
fi

# (3)
exitCode=0
COMMAND WITH A LOT OF ARGUMENTS \
    | AND MAYBE EVEN PIPES \
    | MAYBE OVER MANY LINES \
    || exitCode=$?

# (4) Brittle, must not mix up order of && and ||
COMMAND WITH A LOT OF ARGUMENTS \
    | AND MAYBE EVEN PIPES \
    | MAYBE OVER MANY LINES \
     && exitCode=$? || exitCode=$?

# (5), doesn't work with `set -o pipefail`
COMMAND WITH A LOT OF ARGUMENTS \
    | AND MAYBE EVEN PIPES \
    | MAYBE OVER MANY LINES | cat
exitCode=$PIPESTATUS

# (6) Requires maintaining a function across scripts.
captureExitCode COMMAND WITH A LOT OF ARGUMENTS \
    | AND MAYBE EVEN PIPES \
    | MAYBE OVER MANY LINES
# where
captureExitCode() {
    # any of the above constructs with "$@" as command
}

. Все они либо многословны, либо несколько сложны для визуального анализа, особенно если COMMAND ... - команда многострочного трубопровода. По крайней мере, они плохо сообщают о своих намерениях. В случае captureExitCode функция должна воспроизводиться в разных сценариях.

Есть ли менее подробный встроенный идиом для захвата кода выхода?

1 Ответ

0 голосов
/ 19 марта 2020

Запустите команды проблемати c в под-оболочке и отключите errexit:

(
  set +e
  run buggy code failing without proper error handling
)
exitcode=$?

Пример:

#! /bin/bash

set -e

if ( set +e
     false
   )
then
  echo success
else
  echo failure
fi

Кстати: когда вы пишете канал таким образом обратная цитата не нужна:

echo abc |
  tr a x |
  sed 's/^x/y/'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...