Как получить код ошибки из подоболочки, запущенной в eval

Я пытался найти вопросы, подобные этому, которые охватывают решение для меня, но ни один из них, который я мог бы найти, полностью не отвечал на мой точный вопрос.

Я хотел бы запустить команду в подоболочке внутри вызова eval и получить код состояния, возвращаемый функцией, вызываемой в подоболочке.

Например, я вызываю такую ​​команду:

eval "$(some_command)"
if [ "${?}" -ne 0 ]
then
    # do stuff if `some_command` returned status code not equal to zero
fi

Эта функция some_command возвращает список переменных окружения и их назначений следующим образом:

$ some_command      # Execute some_command in a standard fashion without eval or subshell
some_env_variable='some_value'
another_env_variable='another value'

Цель состоит в том, чтобы запустить эту единственную команду, чтобы добавить эту переменную среды в текущую среду. Единственный способ сделать это — вызвать some_command внутри подоболочки и заставить eval оценить результирующий вывод. Если я сделаю это без подоболочки, eval просто запустит some_command, но не будет оценивать свой вывод, чтобы добавить переменную среды в текущую среду.

Это работает:

$ eval "some_command"
-bash: some_command: command not found
$ echo $?
127

Это работает:

$ $(some_command)
-bash: some_command: command not found
$ echo $?
127

Но это не работает:

$ eval "$(some_command)"
-bash: some_command: command not found
$ echo $?
0

Должен быть какой-то способ получить результирующий код состояния от some_command, но я не смог определить, как это сделать. Любая помощь приветствуется!


person Ian Tait    schedule 10.01.2019    source источник
comment
Насколько я понимаю ваш вопрос, bash(1) - страница руководства Linux ясно. Аргументы считываются и объединяются в одну команду. Затем эта команда считывается и выполняется оболочкой, и ее состояние выхода возвращается как значение eval. Если нет аргументов или есть только нулевые аргументы, eval возвращает 0.   -  person David C. Rankin    schedule 10.01.2019
comment
Может быть, есть способ полностью избежать eval?   -  person Paul Hodges    schedule 10.01.2019
comment
Я знаю, что многие разработчики очень устали от использования eval, потому что это опасно или что-то в этом роде, но это определенно то, что я хотел бы сделать. У меня есть всесторонняя проверка того, что вывод some_command не будет опасен для интерпретации eval. Мне нужно использовать eval, потому что я хочу, чтобы вывод some_command добавлял переменные среды в вызывающий процесс.   -  person Ian Tait    schedule 10.01.2019
comment
@PaulHodges Это единственная ситуация, когда eval практически незаменим; вам нужно доверять программе, чтобы она производила безопасный для оценки результат. ssh-agent — это часто используемый пример, когда он предназначен для использования с eval $(ssh-agent -s).   -  person chepner    schedule 10.01.2019


Ответы (1)


Если вас действительно беспокоит статус выхода, не используйте eval сразу.

if envvars=$(some_command); then
    eval "$envvars"
else
    # do something else
fi

Если вам нужен точный код ошибки, а не просто различать 0 и ненулевое значение:

envvars=$(some_command)
rv=$?  # save it for later if necessary
case $rv in
   0) eval "$envvars" ;;
   1) ... ;;
   2) ... ;;
   # etc
   *) printf 'Some other error %d\n' "$rv" >&2 ;;
esac
person chepner    schedule 10.01.2019
comment
Это будет работать для определения того, была ли команда успешной или нет, но все же не дает мне фактический код состояния в переменной среды, такой как $?. Я хотел бы получить код ошибки и выполнить определенные действия на основе точного значения кода состояния. - person Ian Tait; 10.01.2019
comment
$? должен быть доступен в блоке else. - person Barmar; 10.01.2019
comment
@IanTait Вопрос просто говорит о том, что вы хотите что-то сделать, если статус не 0, он не говорит, что вам нужно различать разные коды. - person Barmar; 10.01.2019
comment
Он говорит, что я хочу захватить код состояния. Из исходного сообщения: я хотел бы запустить команду в подоболочке внутри вызова eval и ПОЛУЧИТЬ КОД СОСТОЯНИЯ, возвращаемый функцией, вызываемой внутри подоболочки. Я внес некоторые изменения, чтобы попытаться сделать это более понятным. - person Ian Tait; 10.01.2019
comment
Там же написано # do stuff if `some_command` returned status code not equal to zero - person Barmar; 10.01.2019
comment
Да, вы должны принять во внимание весь пост, чтобы определить, чего я пытаюсь достичь. Просто посмотреть на одну строку не получится. - person Ian Tait; 10.01.2019
comment
@chepner После вашего редактирования это сработает для меня. Посмотрев на это, мне это кажется очевидным. Я застрял в однострочном мышлении, и мне просто нужно было уйти от этого. Спасибо! - person Ian Tait; 10.01.2019