Аргументы командной строки Bash
Функциональность интерпретатора Bash позволяет работать не только со статистическими данными, записанными в скриптах. Иногда возникает необходимость добавить сценарию интерактивности, позволяя принимать внешние параметры скрипта для манипуляции ими в коде.
В этой статье будет рассмотрено, как принимать аргументы командной строки bash, способы его обработки, проверка опций, а также известные особенности при работе с ними.
Параметры скрипта Bash
Интерпретатор Bash присваивает специальным переменным все параметры, введённые в командной строке. В их состав включено название сценария, выполняемого интерпретатором. Такие переменные называются ещё числовыми переменными, так как в их названии содержится число:
Ниже приведён пример использования одного параметра скрипта Bash:
#!/bin/bash
factorial=1
for (( number = 1; number
Результат работы кода:
Переменная $1 может использоваться в коде точно так же, как и любая другая. Скрипт автоматически присваивает ей значение из параметра командой строки — пользователю не нужно делать это вручную.
Если необходимо ввести дополнительные параметры, их следует разделить в командной строке пробелами.
Пример работы кода:
Командный интерпретатор присвоил числа 5 и 10 соответствующим переменным — $1 и $2.
Также параметрами могут быть и текстовые строки. Однако, если есть необходимость передать параметр, содержащий пробел (например имя и фамилию), его нужно заключить в одинарные или двойные кавычки, так как по умолчанию пробел служит разделителем параметров командной строки:
Пример работы кода:
На заметку: кавычки, которые используются при передаче параметров, обозначают начало и конец данных и не являются их частью.
Если необходимо использовать больше 9 параметров для скрипта, то названия переменных немного изменятся. Начиная с десятой переменной, число, стоящее после знака $, необходимо заключать в квадратные скобки (без внутренних пробелов):
Пример работы кода:
Получение названия скрипта Bash
Как уже упоминалось, имя сценария является самым первым параметром скрипта. Чтобы определить название программы, используется переменная $0. Такая необходимость возникает, например, при написании скрипта, который может выполнять несколько функций. Однако при этом возникает одна особенность, которую нужно учитывать на практике:
Пример работы кода:
Как видно, если строкой, фактически переданной в переменную $0, является весь путь к сценарию, то на вывод будет идти весь путь, а не только название программы.
Если нужен скрипт, выполняющий различные функции с учётом того, под каким именем он был вызван из командной строки, придётся проделать дополнительную работу: удалить сведения о пути, который использовался для его вызова.
Для этого специально предусмотрена небольшая команда. Команда basename возвращает только название скрипта без абсолютного или относительного пути к нему:
Результат работы кода:
Проверка параметров скрипта
Передача параметров Bash вынуждает соблюдать осторожность. Если сценарий написан с применением параметров, но запускается без них, то возникнут проблемы в работе программы.
Если попробовать запустить написанный ранее скрипт test2 без аргументов, то перед выводом команд echo будет отображена ошибка:
Чтобы предотвращать подобные ситуации, необходимо действовать на упреждение — проверять аргументы скрипта на наличие значений. Это настоятельная рекомендация при использовании параметров в командной строке, и только после ревизии стоит пускать их в дело:
Пример работы кода:
В данном случае использовалась опция -n из предыдущей статьи о сравнении строк в Bash для проверки на наличие значения в переменной, которая считала параметр.
Обработка неизветсного числа параметров
Для начала рассмотрим один из часто используемых инструментов при работе с параметрами Bash — команду shift. Её прямое назначение заключается в сдвиге параметров на одну позицию влево. Таким образом, значение из переменной $3 переместится в $2, а из $2 — в $1. Но из $1 значение просто отбросится и не сместится в $0, так как там неизменно хранится название запущенной программы.
Эта команда является эффективным способом обработки всех параметров, переданных сценарию, особенно, когда нельзя заранее узнать их количество. Достаточно лишь обработать $1, сделать сдвиг и повторить процедуру.
Пример работы кода:
Этот скрипт выполняет цикл while, в условии которого указана проверка первого параметра на длину. И если она равна нулю, цикл прерывает свою работу. При положительном результате проверки команда shift сдвигает все параметры влево на одну позицию.
Ещё один вариант использование shift — смещать на несколько позиций. Для этого достаточно через пробел указать количество, на которое будет смещён ряд параметров скрипта.
Пример работы скрипта:
На заметку: при использовании shift нужно быть осторожным, ведь сдвинутые за пределы $1 параметры не восстанавливаются в период работы программы.
Обработка опций в Bash
Помимо параметров скрипт может принимать опции — значения, состоящие из одной буквы, перед которыми пишется дефис. Рассмотрим 3 метода работы с ними в скриптах. Сперва кажется, что при работе с опциями не должно возникать каких-либо сложностей. Они должны быть заданы после имени запускаемой программы, как и параметры. При необходимости можно сделать обработку опций командной строки по такому же принципу, как это делается с параметрами.
По примеру выше можно применять shift для обработки простых опций. С помощью инструкции case можно определять, являются ли аргументы Bash опциями:
Пример работы программы:
Блок case работает правильно вне зависимости от того, как расположены аргументы командной строки bash.
Выводы
Для того, чтобы сделать свою программу более интерактивной, можно использовать параметры Bash. Встроенные переменные, в названиях которых фигурирует число, обозначают порядок указанных для программы параметров.
Команда basename используется для обрезания пути запущенного сценария, что часто необходимо для создания гибких программ. Использование команды shift позволяет эффективно проходить по переданным скрипту параметрам, особенно когда их количество неизвестно.
Написание скриптов на Bash
Если вы уже более опытный пользователь, то, наверное, часто выполняете различные задачи через терминал. Часто встречаются задачи, для которых нужно выполнять несколько команд по очереди, например, для обновления системы необходимо сначала выполнить обновление репозиториев, а уже затем скачать новые версии пакетов. Это только пример и таких действий очень много, даже взять резервное копирование и загрузку скопированных файлов на удаленный сервер. Поэтому, чтобы не набирать одни и те же команды несколько раз можно использовать скрипты. В этой статье мы рассмотрим написание скриптов на Bash, рассмотрим основные операторы, а также то как они работают, так сказать, bash скрипты с нуля.
Основы скриптов
Простейший пример скрипта для командной оболочки Bash:
!/bin/bash
echo «Hello world»
Утилита echo выводит строку, переданную ей в параметре на экран. Первая строка особая, она задает программу, которая будет выполнять команды. Вообще говоря, мы можем создать скрипт на любом другом языке программирования и указать нужный интерпретатор, например, на python:
!/usr/bin/env python
print(«Hello world»)
!/usr/bin/env php
echo «Hello world»;
В первом случае мы прямо указали на программу, которая будет выполнять команды, в двух следующих мы не знаем точный адрес программы, поэтому просим утилиту env найти ее по имени и запустить. Такой подход используется во многих скриптах. Но это еще не все. В системе Linux, чтобы система могла выполнить скрипт, нужно установить на файл с ним флаг исполняемый.
Этот флаг ничего не меняет в самом файле, только говорит системе, что это не просто текстовый файл, а программа и ее нужно выполнять, открыть файл, узнать интерпретатор и выполнить. Если интерпретатор не указан, будет по умолчанию использоваться интерпретатор пользователя. Но поскольку не все используют bash, нужно указывать это явно.
chmod ugo+x файл_скрипта
Теперь выполняем нашу небольшую первую программу:
Все работает. Вы уже знаете как написать маленький скрипт, скажем для обновления. Как видите, скрипты содержат те же команды, что и выполняются в терминале, их писать очень просто. Но теперь мы немного усложним задачу. Поскольку скрипт, это программа, ему нужно самому принимать некоторые решения, хранить результаты выполнения команд и выполнять циклы. Все это позволяет делать оболочка Bash. Правда, тут все намного сложнее. Начнем с простого.
Переменные в скриптах
Написание скриптов на Bash редко обходится без сохранения временных данных, а значит создания переменных. Без переменных не обходится ни один язык программирования и наш примитивный язык командной оболочки тоже.
Возможно, вы уже раньше встречались с переменными окружения. Так вот, это те же самые переменные и работают они аналогично.
Например, объявим переменную string:
Модифицируем наш скрипт:
Bash не различает типов переменных так, как языки высокого уровня, например, С++, вы можете присвоить переменной как число, так и строку. Одинаково все это будет считаться строкой. Оболочка поддерживает только слияние строк, для этого просто запишите имена переменных подряд:
Обратите внимание, что как я и говорил, кавычки необязательны если в строке нет спецсимволов. Присмотритесь к обоим способам слияния строк, здесь тоже демонстрируется роль кавычек. Если же вам нужны более сложные способы обработки строк или арифметические операции, это не входит в возможности оболочки, для этого используются обычные утилиты.
Переменные и вывод команд
Переменные не были бы настолько полезны, если бы в них невозможно было записать результат выполнения утилит. Для этого используется такой синтаксис:
$( команда )
С помощью этой конструкции вывод команды будет перенаправлен прямо туда, откуда она была вызвана, а не на экран. Например, утилита date возвращает текущую дату. Эти команды эквивалентны:
Понимаете? Напишем скрипт, где будет выводиться hello world и дата:
string1=»hello world »
string2=$(date)
Теперь вы знаете достаточно о переменных, и готовы создать bash скрипт, но это еще далеко не все. Дальше мы рассмотрим параметры и управляющие конструкции. Напомню, что это все обычные команды bash, и вам необязательно сохранять их в файле, можно выполнять сразу же на ходу.
Параметры скрипта
Не всегда можно создать bash скрипт, который не зависит от ввода пользователя. В большинстве случаев нужно спросить у пользователя какое действие предпринять или какой файл использовать. При вызове скрипта мы можем передавать ему параметры. Все эти параметры доступны в виде переменных с именами в виде номеров.
Переменная с именем 1 содержит значение первого параметра, переменная 2, второго и так далее. Этот bash скрипт выведет значение первого параметра:
Управляющие конструкции в скриптах
Создание bash скрипта было бы не настолько полезным без возможности анализировать определенные факторы, и выполнять в ответ на них нужные действия. Это довольно-таки сложная тема, но она очень важна для того, чтобы создать bash скрипт.
В Bash для проверки условий есть команда Синтаксис ее такой:
if команда_условие
then
команда
else
команда
fi
Эта команда проверяет код завершения команды условия, и если 0 (успех) то выполняет команду или несколько команд после слова then, если код завершения 1 выполняется блок else, fi означает завершение блока команд.
Но поскольку нам чаще всего нас интересует не код возврата команды, а сравнение строк и чисел, то была введена команда [[, которая позволяет выполнять различные сравнения и выдавать код возврата зависящий от результата сравнения. Ее синтаксис:
[[ параметр1 оператор параметр2 ]]
Теперь объединением все это и получим скрипт с условным выражением:
Конечно, у этой конструкции более мощные возможности, но это слишком сложно чтобы рассматривать их в этой статье. Возможно, я напишу об этом потом. А пока перейдем к циклам.
Циклы в скриптах
Преимущество программ в том, что мы можем в несколько строчек указать какие действия нужно выполнить несколько раз. Например, возможно написание скриптов на bash, которые состоят всего из нескольких строчек, а выполняются часами, анализируя параметры и выполняя нужные действия.
Первым рассмотрим цикл for. Вот его синтаксис:
for переменная in список
do
команда
done
Перебирает весь список, и присваивает по очереди переменной значение из списка, после каждого присваивания выполняет команды, расположенные между do и done.
Например, переберем пять цифр:
Или вы можете перечислить все файлы из текущей директории:
Как вы понимаете, можно не только выводить имена, но и выполнять нужные действия, это очень полезно когда выполняется создание bash скрипта.
while команда условие
do
команда
done
Как видите, все выполняется, команда let просто выполняет указанную математическую операцию, в нашем случае увеличивает значение переменной на единицу.
Хотелось бы отметить еще кое-что. Такие конструкции, как while, for, if рассчитаны на запись в несколько строк, и если вы попытаетесь их записать в одну строку, то получите ошибку. Но тем не менее это возможно, для этого там, где должен быть перевод строки ставьте точку с запятой «;». Например, предыдущий цикл можно было выполнить в виде одной строки:
Все очень просто я пытался не усложнять статью дополнительными терминами и возможностями bash, только самое основное. В некоторых случаях, возможно, вам понадобиться сделать gui для bash скрипта, тогда вы можете использовать такие программы как zenity или kdialog, с помощью них очень удобно выводить сообщения пользователю и даже запрашивать у него информацию.
Выводы
Теперь вы понимаете основы создания скрипта в linux и можете написать нужный вам скрипт, например, для резервного копирования. Я пытался рассматривать bash скрипты с нуля. Поэтому далеко не все аспекты были рассмотрены. Возможно, мы еще вернемся к этой теме в одной из следующих статей.
Введение в 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
Подробнее о test можно узнать в справочнике командой man test.
Основная конструкция 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
Примечание. Так и не понял, что делает этот скрипт. В моём случае используется CentOS 7 и по умолчанию там нет monitor, хотя в скрипте явно написано: Где-то пол часа гуглил для CetOS программу monitor, но так и не нашёл. И вообще не понятно каким тут боком monitor если используется ps aux. В любом случае так и не понял, что делает этот срипт. Большая просьба помочь решить этот вопрос, чтобы откорректировать текст и/или скрипт.
Сценарий в листинге 7 состоит из двух частей. Во-первых, есть цикл while. Во-вторых, есть всё, что нужно выполнить, когда цикл while больше не оценивается как true.
Ядром цикла while является команда ps, которая имеет значение $1.
Вывод команды ps aux перенаправляются в /dev/tty11. Это позволяет позже прочитать результаты из tty11, если это необходимо, но они не отображаются по умолчанию.
После операторов while следуют команды, которые необходимо выполнить, если проверяемое условие истинно. В данном случае это команда sleep 5, которая приостанавливает выполнение скрипта на 5 секунд.
Пока условие оператора while истинно, цикл продолжает выполняться. Если же условие ложно (что в данном случае означает, что процесс больше не доступен), то цикл останавливается и могут выполняться команды, следующие за ним.


























