Введение в Bash Shell

Всем привет. Это перевод из книги по подготовке к экзамену RedHat RHCE. На мой взгляд очень доступно рассказывается об основах bash.

Сценарии оболочки — наука сама по себе. Не вдаваясь в подробности всего, что происходит «под капотом», вы узнаете, как применять базовые элементы для написания собственных скриптов, и анализировать, что происходит в сторонних сценариях оболочки.

Понимание основных элементов сценариев оболочки

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

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

Ниже показан очень простой скрипт:

Здесь содержатся несколько элементов, которые должны использоваться во всех скриптах. Для начала, есть shebang — это строка #!/bin/bash. Когда скрипт запускается из родительской оболочки, он открывает подоболочку, в которой и выполняются команды, указанные в скрипте.

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

Также могут быть указаны другие оболочки. Например, если ваш скрипт содержит код на языке Perl, shebang должен быть #!/usr/bin/perl. Начинать сценарий с shebang является хорошей практикой; если он опущен, код сценария будет выполняться такой же оболочкой, которая используется для запуска скрипта.

Сразу после shebang расположена часть, объясняющая, о чем сценарий. Несколько строк комментариев в начале каждого сценария — хорошая идея. В коротком скрипте часто очевидно, что он делает, но когда сценарий становится длиннее, и по мере того, как всё больше людей вовлекаются в его написание и поддержку, становится менее понятно, что авторы намереваются сделать.

Чтобы избежать такой ситуации, убедитесь, что вы добавили строки комментариев, начиная каждую символом #. Комментарии могут быть не только в первых строках, но и в начале каждого подраздела сценария. Это наверняка поможет, если вы прочитаете свой скрипт через несколько месяцев!

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

Независимо от того, в какой позиции он используется, всё от символа # и до конца строки является комментарием.

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

В конце скрипта я включил инструкцию exit 0. Оператор выхода сообщает родительской оболочке, был ли сценарий успешным. Состояние выхода последней команды в сценарии является состоянием выхода самого сценария, если только команда exit 0 не используется в конце сценария.

Полезно знать, что вы можете работать с exit, чтобы сообщить родительской оболочке, как все прошло.

Также вы можете разместить сценарий в каталоге /bin, после чего в любом месте файловой системы просто ввести имя файла, и сценарий выполнится.

Командой vi /bin/datetime создадим в каталоге /bin файл с именем datetime. В созданный файл вставим это содержимое:

Сохранив файл, введите chmod +x /bin/datetime, чтобы дать файлу права на выполнение. Перейдите, к примеру, в домашний каталог с помощью команды cd

и просто введите datetime.

Перейдите, к примеру, в домашний каталог cd

и просто введите datetime.

Использование переменных и входных данных

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

Использование позиционных параметров

При запуске скрипта можно использовать аргументы. Аргумент — это всё, что вы помещаете за командой сценария. Аргументы могут быть использованы для того, чтобы сделать скрипт более гибким. Возьмём команду useradd lisa. В этом примере команда — это useradd, а её аргумент — lisa — указывает, что нужно сделать.

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

В тексте сценария первый аргумент обозначается $1, второй аргумент — $2 и т. д. Листинг 1 показывает, как можно использовать аргументы. Попробуйте запустить этот код, указав в качестве параметров любые имена пользователей.

Под параметрами подразумевается ввод данных перед запуском скрипта. В данном случае в качестве параметров после имени скрипта argument я указал lisa, lori и bob:

В Листинге 2 представлены два новых элемента, которые относятся к аргументам:

Итак, пока есть аргументы, тело сценария выполняется.

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

Давайте попробуем воспользоваться скриптом из листинга 2 в этом примере:

Переменные

Переменная — это метка, которая используется для обозначения определённого места в памяти, которое содержит определённое значение. Переменные могут быть определены статически с помощью NAME=value или динамическим способом. Существует два решения для динамического определения переменной:

Листинг 3. Пример скрипта, использующего команду read

* — на самом деле тремя источник (прим. переводчика)

Обратите внимание, что при написании команды test с квадратными скобками важно использовать пробелы после открывающей скобки и перед закрывающей скобкой, без пробелов команда не будет работать.

Обратите внимание, что оператор then следует сразу за test. Это возможно, потому что используется точка с запятой (;). Точка с запятой является разделителем команд и может заменить новую строку в скрипте.

В операторе then выполняются две команды: команда echo, которая отображает сообщение на экране, и команда read.

Команда read останавливает сценарий, чтобы пользовательский ввод мог быть обработан и сохранен в переменной TEXT. Поэтому read TEXT помещает все введённые пользователем данные в переменную TEXT, которая будет использоваться позже в скрипте.

Следующая часть представлена оператором else. Команды после оператора else выполняются во всех других случаях, что в данном случае означает «иначе, если аргумент был предоставлен». Если это так, то определяется переменная TEXT и ей присваивается текущее значение $1.

Вы можете попрактиковаться на этом примере при работе с вводом.

Использование условий и циклов

Как вы уже видели, в скрипте могут использоваться условные операторы. Эти условные операторы выполняются только в том случае, если определённое условие выполняется.

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

if then else

Основная конструкция if есть if… then… fi.

Она сравнивает одно условие, как показано в следующем примере:

В листинге 3 вы увидели, как можно оценить два условия, включая else в выражении. В листинге 4 показано, как можно оценить несколько условий от if до else. Это полезно, если нужно проверить много разных значений.

Обратите внимание, что в этом примере также используются несколько команд test.

Листинг 4. Пример с if then else

Вместо написания полных операторов if… then вы можете использовать логические операторы || а также &&. || является логическим «ИЛИ» и выполнит вторую часть оператора, только если первая часть не верна; && является логическим «И» и выполнит вторую часть оператора только в том случае, если первая часть верна.

Рассмотрим эти две строки:

В первом примере выполняется проверка, чтобы увидеть, пуст ли $1. Если эта проверка верна (что, в основном, означает, что команда завершается с кодом выхода 0), выполняется вторая команда.

Во втором примере команда ping используется для проверки доступности хоста.
В этом примере используется логическое «ИЛИ» для вывода текста «node is not available» в случае неудачной команды ping.

Вы обнаружите, что часто вместо условного оператора if будут использоваться && и ||. В упражнении ниже вы можете попрактиковаться в использовании условных операторов, используя либо if… then… else, либо && и ||.

Упражнение. Использование if… then… else

В этом упражнении вы поработаете над сценарием, который проверяет что является файлом, а что каталогом.

Цикл for

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

Цикл for всегда начинается с ключевого слова for, за которым следует условие, которое необходимо проверить. Затем следует ключевое слово do, за которым следуют команды, которые должны быть выполнены, если условие истинно, завершается цикл с помощью ключевого слова done.

В примере, приведённом в листинге 5, вы можете увидеть, что условие представляет собой диапазон чисел в круглых скобках, назначенных переменной COUNTER.

Маленькое пояснение

Внутри ((… )) вычисляются арифметические выражения и возвращается их результат. Например, в простейшем случае, конструкция a=$(( 5 + 3 )) присвоит переменной «a» значение выражения «5 + 3», или 8. Кроме того, двойные круглые скобки позволяют работать с переменными в стиле языка C.

В листинге 6 вы можете увидеть один из моих любимых однострочников с for. Диапазон определяется на этот раз как последовательность чисел, начиная со 100 и доходя до 104.

Обратите внимание, как определяется диапазон: сначала вы указываете первое число, затем две точки и указываете последнее число в диапазоне. При этом с for i in для каждого из этих номеров присваивается переменная i. Каждое из этих чисел присваивается переменной i и затем выполняется команда ping, где опция -c 1 гарантирует, что отправляется только один запрос.

Результат выполнения команды ping не учитывается, поэтому её вывод перенаправляется в /dev/null. На основании состояния выхода команды ping выполняется часть выражения за &&. Таким образом, если хост доступен, отображается строка, указывающая, что он работает.

Понимание while и until

Сценарий в листинге 7 состоит из двух частей. Во-первых, есть цикл while. Во-вторых, есть всё, что нужно выполнить, когда цикл while больше не оценивается как true.

Ядром цикла while является команда ps, которая имеет значение $1.

Вывод команды ps aux перенаправляются в /dev/tty11. Это позволяет позже прочитать результаты из tty11, если это необходимо, но они не отображаются по умолчанию.

После операторов while следуют команды, которые необходимо выполнить, если проверяемое условие истинно. В данном случае это команда sleep 5, которая приостанавливает выполнение скрипта на 5 секунд.

Пока условие оператора while истинно, цикл продолжает выполняться. Если же условие ложно (что в данном случае означает, что процесс больше не доступен), то цикл останавливается и могут выполняться команды, следующие за ним.

* — по крайней мере в CentOS по умолчанию работает. (при. переводчика)

Обычно при использовании команды mail в интерактивном режиме открывается редактор, в котором можно написать тело сообщения. Этот редактор закрыт, предоставляя строку, которая имеет только точку. В этой команде точка предоставляется путём перенаправления STDIN. Это позволяет обрабатывать сообщение без каких-либо дополнительных требований к пользовательской активности.

Цикл while — это противоположность циклу until, пример которого приведён в листинге 8. until запускает итерацию, которая длится до тех пор, пока условие не станет истинным.

В листинге 8 он используется для фильтрации выходных данных команды users по вхождению $1, которое будет именем пользователя. Пока эта команда не верна, итерация продолжается. Когда имя пользователя найдено в выводе пользователей, итерация закрывается, и после цикла until выполняются остальные команды.

Понимание case

Последний из важных итерационных циклов — это case*. Оператор case используется для оценки ряда ожидаемых значений. В частности, инструкции case важны в сценариях запуска Linux, которые в предыдущих версиях использовались для запуска служб.

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

В листинге 9 вы можете увидеть работу оператора case, который использовался в ранней версии для запуска практически любой службы.

case имеет несколько особенностей. Сначала идет строка — case последовательность in. Затем следует список всех возможных значений, которые необходимо оценить. Каждый элемент закрывается скобкой ).

Затем следует список команд, которые необходимо выполнить, если использовался конкретный аргумент. Список команд закрывается двойной точкой с запятой ;; может использоваться непосредственно после последней команды и может использоваться в отдельной строке.

Также обратите внимание, что *) относится ко всем другим параметрам, не указанным ранее. Это «всеохватывающий» оператор.

Цикл итераций case завершается оператором esac.

Обратите внимание, что последовательности в case выполняются по порядку. Когда будет выполнено первое совпадение, оператор case не будет ничего оценивать.

В рамках оценки могут использоваться шаблоны, подобные шаблону. Это показано в *) последовательности, которая соответствует всему. Но вы также можете использовать последовательности, такие как start|Start|START), чтобы соответствовать использованию другого case.

Отладка скриптов в Bash

Bash get exit code of command on a Linux / Unix

Every Linux or Unix command executed by the shell script or user has an exit status. Exit status is an integer number. 0 exit status means the command was successful without any errors. A non-zero (1-255 values) exit status means command was a failure.

How to find out the exit code of a command

Bash get exit code of command

How to get the exit code of a command such as date and date-foo-bar

Bash get exit code of command – How to use exit codes in shell scripts

How do I set an exit code for my own shell scripts?

The exit command cause normal shell script termination. It exits the shell with a status of N. The syntax is:

A sample shell script to get the exit code of a command

Recommend exit code for your shell scripts

Exit Codes With Special Meanings
Exit status Description
1 Catchall for general errors
2 Misuse of shell builtins (according to Bash documentation)
126 Command invoked cannot execute
127 Command not found
128 Invalid argument to exit command
128+n Fatal error signal “n”
130 Bash script terminated by Control-C
255* Exit status out of range

How to deal with the exit codes of all piped commands

Conclusion

This page showed how to use exit codes on Linux or Unix based system and how to get the exit status/code of command. See man pages by typing the man command or help command:
man bash
help exit
For more info see:

? Get the latest tutorials on Linux, Open Source & DevOps via RSS feed or Weekly email newsletter.

? 4 comments so far. add one

Comments on this entry are closed.

One of the best Unix exit code tutorial with examples. Thank you. I used it on my macOS macMini desktop.

Hi, I just completed 9 captchas — 18 3×3 grids. I come here for a quick tutorial to remind myself of something I already know, in most cases, for one minute so as not to lose my train of thought. Thank-you! But I don’t have the time for the captchas. Please find another solution to whatever problem you are trying to solve.

Captchas are only needed when posting comments to avoid spam. However, Cloudflare might trigger Captchas when it detects IP address with bad reputation.

Hi Vivek,
Love your site, and I’ve learned a lot from it. It’s a great resource.
I normally use a self-administered proxy/VPN when using a browser for privacy reasons. Unfortunately I can’t control which IP address I get without becoming an ISP or a cloud provider myself. Cloudflare probably sees my IP address and knows that it is in the range for cloud provider X, and not from a company or residential IP address, which triggers the captcha.
So in this case it is unfortunately targetting a normal/not-spamming user. I understand that you are doing this so as to not have to deal with spam or other issues; and my behaviour is probably that of only a tiny percentage of users.
Trade-offs and unintended consequences, right? Anyway, I thought it might be useful to hear from someone for whom this was causing issues. In order to check on this and reply today, I ‘only’ had to do 4 captchas.
Thank you kindly for your excellent website.

Источники:

https://habr. com/ru/post/471242/

https://www. cyberciti. biz/faq/bash-get-exit-code-of-command/

Понравилась статья? Поделиться с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: