Bash возврат значения

Глава 6. Завершение и код завершения

. эта часть Bourne shell покрыта мраком, тем не менее все пользуются ею.

Команда exit может использоваться для завершения работы сценария, точно так же как и в программах на языке C. Кроме того, она может возвращать некоторое значение, которое может быть проанализировано вызывающим процессом.

Каждая команда возвращает код завершения (иногда код завершения называют возвращаемым значением ). В случае успеха команда должна возвращать 0 , а в случае ошибки — ненулевое значение, которое, как правило, интерпретируется как код ошибки. Практически все команды и утилиты UNIX возвращают 0 в случае успешного завершения, но имеются и исключения из правил.

Аналогичным образом ведут себя функции, расположенные внутри сценария, и сам сценарий, возвращая код завершения. Код, возвращаемый функцией или сценарием, определяется кодом возврата последней команды. Команде exit можно явно указать код возврата, в виде: exit nnn , где nnn — это код возврата (число в диапазоне 0 — 255 ).

Когда работа сценария завершается командой exit без параметров, то код возврата сценария определяется кодом возврата последней исполненной командой.

Код возврата последней команды хранится в специальной переменной $?. После исполнения кода функции, переменная $? хранит код завершения последней команды, исполненной в функции. Таким способом в Bash передается «значение, возвращаемое» функцией. После завершения работы сценария, код возврата можно получить, обратившись из командной строки к переменной $?, т.е. это будет код возврата последней команды, исполненной в сценарии.

Пример 6-1. завершение / код завершения

Переменная $? особенно полезна, когда необходимо проверить результат исполнения команды (см. Пример 12-27 и Пример 12-13).

Символ !, может выступать как логическое «НЕ» для инверсии кода возврата.

Пример 6-2. Использование символа ! для логической инверсии кода возврата

В отдельных случаях коды возврата должны иметь предопределенные значения и не должны задаваться пользователем.

Возврат логического значения из функции Bash

Я хочу написать функцию bash, которая проверяет, имеет ли файл определенные свойства и возвращает true или false. Тогда я могу использовать его в своих сценариях в «if». Но что мне вернуть?

то я использую его следующим образом:

конечно, это не работает. Как это можно сделать?

Используйте значение 0 для true и 1 для false.

Edit

Из комментария @amichair, это также возможно

Почему вы должны заботиться о том, что я говорю, несмотря на то, что есть ответ на более чем 200-й верхний ответ

Это не то, что 0 = true и 1 = false . Это: ноль означает успех и ненулевой означает отказ.

Пока выбранный ответ технически «истинный» , пожалуйста, не помещайте return 1 ** в свой код для false. У него будет несколько неудачных побочных эффектов.

  • Опытные разработчики будут замечать вас как любителя (по этой причине ниже).
  • Опытные разработчики этого не делают (по всем причинам ниже).
  • Это склонность к ошибкам.
    • Даже опытные разработчики могут ошибочно принимать 0 и 1 как ложные и истинные (по причине выше).
  • Он требует (или будет поощрять) посторонние и смешные комментарии.
  • Это на самом деле менее полезно, чем неявные статусы возврата.

Этот ответ вот-вот станет потрясающим. Я был бы благодарен за ваше продвижение.

Узнайте несколько bash

bash manual говорит (акцент мой)

Причина, что функция оболочки прекращает выполнение и возвращает значение n своему вызывающему. Если n не предоставляется, возвращаемое значение — это статус завершения последней выполненной команды в функции.

Поэтому нам не нужно ВСЕ использовать 0 и 1, чтобы указать True и False. Тот факт, что они делают это, — это, по сути, тривиальное знание, полезное только для отладки кода, опроса вопросов и раздувания умов новичков.

в противном случае статус возврата функции — это статус завершения последней выполненной команды

($?) Расширяется до статуса завершения последнего выполненного проекта переднего плана.

Конвейер представляет собой последовательность одной или нескольких команд, разделенных одним из операторов управления | или ‘| &.

Читайте так же:  Отозвана лицензия у северной казны

Да. Они сказали, что 1 команда — это конвейер. Поэтому все три из этих цитат говорят одно и то же.

  • $? сообщает вам, что произошло последним.
  • Он пузырится вверх.

Итак, хотя @Kambus продемонстрировал, что при такой простой функции вообще нет return . Я думаю, что демонстрация @Erik была нереалистично простой по сравнению с потребностями большинства людей, которые прочтут это.

Если функция вернет свой последний статус выхода из команды, зачем вообще использовать return ? Потому что это заставляет функцию прекратить выполнение.

Остановить выполнение в нескольких условиях

Строка 04 является явным [-ish] возвратом true, потому что RHS && выполняется только в том случае, если LHS был истинным

Линия 09 возвращает либо true, либо false, соответствующий статусу строки 08

Строка 13 возвращает false из-за строки 12

(Да, это можно поиграть в гольф, но весь пример надуман.)

Другой общий шаблон

Обратите внимание, как настройка переменной status демистифицирует значение $? . Но реальным выводом является то, что «если не существует статуса» или наоборот «если статус выхода» можно прочитать вслух и объяснить их смысл.

** Если вы абсолютно настаиваете на использовании return 1 для false, я предлагаю вам хотя бы использовать return 255 . Это приведет к тому, что ваш будущий «я» или любой другой разработчик должен поддерживать ваш код на вопрос «почему это 255?». Тогда они, по крайней мере, обратят на них внимание и получат больше шансов избежать ошибки.

Будьте внимательны при проверке каталога только с опцией -d!
если переменная $1 пуста, проверка все равно будет успешной. Разумеется, проверьте также, что переменная не пуста.

Это может сработать, если вы перепишете это function myfun() < . return 0; else return 1; fi;>как это function myfun() < . return; else false; fi;>. То есть, если false является последней инструкцией в функции, вы получаете ложный результат для целой функции, но return прерывает функцию с истинным результатом. Я верю, что это верно для моего переводчика bash, по крайней мере.

Возврат значения функции и последующая обработка значения

Всем доброго времени суток.

Подскажите, почему такая штука. Допустим, есть функция и из неё я возвращаю 0 или 1. Но, if и test по разному обрабатывают return .

Команда test обрабатывает успешность выполнения функции или как это работает? Как можно еще обработать return ?

А если назвать mytest ?

Такое же поведение. Дал вообще другие название:

Насколько правильный такой синтаксис?

check_status возвращает 1, что bash’ем понимается как false; echo ok возвращает 0, то есть true.

false && true || echo not ok

Меня смущает вопрос могу ли я использовать конструкцию check_status && echo ok || echo not ok вместо if check_status; then echo ok; else echo not ok; fi . Насколько они равнозначны?

В этом контексте они логически эквивалентны, поскольку echo всегда вернет true. В случаях, вроде

— всё зависит от значений, которые вернут foo и bar. Надежней писать полную конструкцию.

Я хочу использовать вот как:

Т.е. я хочу обратиться из функции, которая перезапустила репликацию к функции, которая проверяет её статус и вернуть результат перезапуска.

Думаю, что это не та ситуация, в которой надо экономить десятки байт. Если здесь написать вложенный if, понятность кода только улучшится. В тех случаях, когда вложенных условий становится слишком много, стоит выносить фрагмент в отдельную функцию.

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

Когда вы используете конструкцию «if », то bash выполняет команду (или функцию) и анализирует её код возврата.

Когда вы используете конструкцию if [[ check_status ]] . или if [ check_status ] . то bash воспринимает эту конструкцию как сокращение для:

или, что аналогично:

Для наглядности попробуйте добавить в вашу функцию какое-нибудь echo и вы увидите, что в первом варианте ваша функция вообще не вызывается. Ну или просто включите режим отладки «set -x».

1 — это статус ошибки в shell.

Статус успеха — 0.

А здесь, как выше уже написали, test вообще не вызывается, поскольку выступает обычным тестовым аргументом для команды [[.

. Как можно еще обработать return?

В bash есть специальная переменная $?, которой после выполнения любой команды/функции присваивается соответствующий код возврата. Только с этой переменной нужно обходиться аккуратно — предварительно, сразу после выполнения команды, её нужно сохранять в какой-нибудь локальной переменной, чтобы не запортить следующими командами, а потом уже проверять значение.
Типа:

Читайте так же:  Купля продажа автомобильных красивых номеров

P.S. Работая с bash рекомендую всегда иметь под рукой Advanced Bash−Scripting Guide.

Про $? я знаю, в данном случае избыточна. За справочник спасибо.

Лучше бери хоть brainfuck вместо баша, меньше будешь вот так спотыкаться.

Счетчик в цикле while не меняет значение

Здравствуйте! Подскажите, пожалуйста, почему счетчик не меняет свое значение после команды let INDEX++ ?

почему счетчик не меняет свое значение после команды let INDEX++

Я перепробовал кучу вариантов, при форме записи let «INDEX+=1» счётчик также стоит на месте

откуда ты это знаешь? я не вижу ни одной команды, которая бы выводила значение этой пемеренной

В смысле с такими кавычками «»

У меня твой скрипт нормально работает. Может, на месте /bin/sh у тебя действительно sh, а не bash?

Попробуй #!/bin/sh заменить на #!/bin/bash

Может потому что у тебя в выражении фигня, которую bash не понимает?

И да, плюсую вышеотписавшихся ораторов насчет /bin/bash в качестве shebang

Заменил #!/bin/sh на #!/bin/bash — заработало! Спасибо, Kroz !

А вообще можно сделать на bash что-нибудь похожее на шкалу выполненной работы?

Встроенная команда let вычисляет значение арифметического выражения и возвращает его код возврата
0 (TRUE) когда не равняется 0 (arithmetic “true”)
1 (FALSE) когда равняется 0 (arithmetic “false”)

bash. получить описание кода возврата имея только код

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

нет, я конечно понимаю, что можно написать мегасвитч или массив со всеми кодами ошибок. но неужели нет какого-то стандартного способа?

Linux Exp Group

Возврат значений из функций Bash

Функции Bash, в отличие от функций в большинстве языков программирования, не предоставляют прозрачной возможности вернуть результат выполнения. Когда Bash-функция завершается, она возвращает статус этого завершения: нуль для успешного завершения, не-нуль — для сигнализации о проблемах. Для возврата значений можно задать глобальную переменную для забора в нее значения, или использовать подстановку, или передать значение в локальную переменную. Примеры ниже показывают, как использовать эти подходы.

Хотя Bash возвращает код завершения, какое это имеет практическое значение? что с ним делать? Код возврата содержится в переменной $? . Если функция по каким-либо причинам не возвращает код завершения, этим кодом будет служить код возврата последней инструкции внутри функции. Поэтому нужны ухищрения.

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

function myfunc()
<
myresult=’some value’
>

myfunc
echo $myresult

Этот код устанавливает глобальную переменную myresult внутри функции result. Довольно просто, но, как всем нам хорошо известно, установка глобальных переменных в больших программах может привести к появлению трудноотлавливаемых багов.

Лучшей практикой будем считать использование локальных переменных. Основной проблемой, которую нужно преодолеть, это как вернуть значение вызывающему функцию процессу. Один из способов — использовать командную подстановку:

function myfunc()
<
local myresult=’some value’
echo «$myresult»
>

result=$(myfunc) # or result=`myfunc`
echo $result

Здесь result появится в потоке стандартного вывода и появляется возможность захватить его с помощью подстановки. Дальше переменная может быть использована при необходимости.

Другой путь возвратить значение — передать в функцию имя переменной в качестве одного из параметров командной строки и в нее записать результат выполнения функции:

function myfunc()
<
local __resultvar=$1
local myresult=’some value’
eval $__resultvar=»‘$myresult'»
>

myfunc result
echo $result

Поскольку мы имеем некое имя переменной, в которой храним имя переменной с результатом, мы можем задать возвращаемую переменную непосредственно в командной строке. Здесь необходимо использовать eval для присвоения значения.

Когда мы храним имя переменной, переданное из командной строки, следует быть уверенным, что именно это имя не будет использовано вызывающим процессом (поэтому я на всякий случай использую здесь __resultvar, а не resultvar). Если это все-таки произойдет, переменная результата не будет задана. К примеру, нижеследующая конструкция работать не будет:

function myfunc()
<
local result=$1
local myresult=’some value’
eval $result=»‘$myresult'»
>

myfunc result
echo $result

Причина, по которой это не работает, заключается в особенностях инструкции eval. Когда eval выполняет вторую интерпретацию и вычисляет result=’some value’, result с этого момента — локальная переменная и не выйдет за пределы функции.

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

Читайте так же:  Кирьянова нотариус нефтеюганск

function myfunc()
<
local __resultvar=$1
local myresult=’some value’
if [[ «$__resultvar» ]]; then
eval $__resultvar=»‘$myresult'»
else
echo «$myresult»
fi
>

myfunc result
echo $result
result2=$(myfunc)
echo $result2

Если имя не было передано в параметре, возвращаемое значение будет выдано на станартный вывод.

Bash: Как вернуть назад параметр

я новичек, поэтому если есть более оптимальтый способ— скажите, (с целью разгрузить тело скрипта от повторяющегося кода, выделяю его в отдельный файл «библиотеку») передаю параметр скрипту: bash «/tmp/123» param

/tmp/123 #!/bin/bash ccc=«$1» exit 0

после завершения скрипта, пишу в консоли echo «$ccc», ожидая что раз в дочернем скрипте была обьявлена переменная ссс, то и в родительском скрипте (в данном случае терминале) она будет видна. этого не происходит. как это можно исправить?

Когда ты дергаешь дочерний скрипт, он открывается в subshell.
Следовательно, из него ты переменные не передашь.

Зачем вам это нужно ?

Если вам нужно выставлять значение некоторых переменных, определённых заранее в файла, то нужно (можно) делать так:
1. В начале создать файл, в котором будут определены переменные

А так при выполнении скрипта запускается отдельный интерпретатор. Но вы можете поступить по аналогии, в скрипте выводить нужные значения в файл, а после выполнения скрипта их выставлять.

хм,а как сделать так, чтобы можно было бы возвращать параметры?

Неправильная логика. Всё, что было объявлено в локальном скрипте уничтожается после его завершения. Всё, что было объявлено в родителе, доступно всем детям.

В твоём случае надо подключать файл с переменными/повторяющимися функциями в основном скрипте так

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

Переведите, если вам не понятно.

Зачем вам возвращать значение переменной в ваш интерпретатор ?

Хм, перевод, как я понимаю, такой: Переменные в дочерней оболочке не видимы снаружи этой оболочки, они недоступны для родительского процесса. Они локальные переменные.

У меня задача: есть скрипт (в котором много раз повторяется один и тот же кусок кода, почти без изменений) Этот кусок кода получает 4 переменные (обрабатывает их, и выдает в виде ответа одну переменную)

Так вот: 1)Этот кусок кода большой, и очень мешает читать остальной код, поэтому я хочу выделить его в отдельный модуль(если это возможно, соответственно, ему надо как-то передать параметры, и получить от него ответ) 2) желательно сделать это не через файл, т.к. обращение к винчестеру будет частым

а не проще запилить 1 функцию и все дубли заменить на вызов этой функции с нужными параметрами?
и если таки хочешь в родителя перетащить переменную из дочки, то почему бы в внешнем_скрипте не выводить результат овер echo?
ну а в родителе делать что-то типа

ему надо как-то передать параметры, и получить от него ответ

тред не читай@сразу отвечай?

То есть ТС бы твой ответ распарсил? Когда человек говорит что он новичек я считаю нужно как можно точнее все показать.

нужно как можно точнее все показать.

ок, тогда почему я не вижу экранирования и всяких < >вокруг переменных?

Потому что быдлокод.

Всё, что было объявлено в родителе, доступно всем детям.

Советую больше узнать про export.

Что именно? Вот это?

Так вот: 1)Этот кусок кода большой, и очень мешает читать остальной код, поэтому я хочу выделить его в отдельный модуль(если это возможно, соответственно, ему надо как-то передать параметры, и получить от него ответ

1. Можно сделать в том же скрипте функцию, и передавать ей параметры (кстати bash умеет ещё и локальные параметры, а по умолчанию они гнлобальные, по всему скрипту)

2. Один скрипт можно разделить на несколько файлов, и включать другие файлы командой source или точкой «.». Надо понимать, что это не аналог «библиотеки», а просто файл внутри файла. Т.е. с т.з. интерпретатора это один большой скрипт.

3. Можно вызывать дочерние скрипты, но передавать параметры можно только ТУДА (см. export). Обратно вы получаете только код возврата, которые лучше всего делать 0 (успех) или 64..127 (ошибка).

Обратно вы получаете только код возврата

чушь не пори, ей больно.

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