функции bash, локальные переменные и коды выхода

В функции bash я пытаюсь захватить вывод команды вместе с кодом выхода. Как правило, моя форма

some_function() {
local rv=$(some_other_function)
local code=$?
echo "$rv"
return $code
}

но я замечаю, что всякий раз, когда я использую "local", тогда $? ВСЕГДА 0. Как будто он фиксирует результат присваивания, а не вызываемую функцию. Если я не использую local, то все работает как положено:

$ foo() { local rv=$(false); echo "code is $?"; }
$ foo
code is 0
$ foo() { rv=$(false); echo "code is $?"; }
$ foo
code is 1

Может кто-то объяснить это мне? Очевидно, здесь что-то фундаментальное, чего я просто не понимаю.


person user2990007    schedule 03.03.2021    source источник
comment
Есть еще одна проблема с local rv=$(some_other_function) - в некоторых оболочках (кроме bash) вывод some_other_function будет разбит по словам перед передачей в local; первое слово будет присвоено rv, а остальные будут обрабатываться как отдельные идентификаторы, которые будут помечены как локальные переменные (за исключением тех, которые не являются действительными идентификаторами). Безопаснее всего всегда заключать подстановку команд в двойные кавычки, например local rv="$(some_other_function)", как и ссылки на переменные.   -  person Gordon Davisson    schedule 03.03.2021


Ответы (1)


Может кто-то объяснить это мне?

Проще говоря, в большинстве случаев $? имеет статус выхода последней выполненной команды. последняя команда - local. Статус возврата local равен нулю - он успешно сделал rv локальной переменной. Глупый пример:

echo $(false) $(true) $(false)
^^^^ - this is the last command executed
# $? here has exit status of **echo**

Отделите присвоение от local:

local rv code
# Assignment is not a "command", in the sense it preserves exit status.
# The last command executed in assignment is the one inside `$(...)`.
rv=$(some_other_function)
code=$?  # will have the exit status of expression executed inside $(...)

Проверьте свои скрипты с помощью http://shellcheck.net. Shellcheck предупреждает о таких ошибках.

person KamilCuk    schedule 03.03.2021
comment
В частности, это вики-запись об этой проблеме: github.com/koalaman/shellcheck/wiki/SC2155 - person glenn jackman; 03.03.2021