В переменную допускается подставлять как числовые значения, так и ASCII символы.
Пример: $ for i in 1 2 A B Abc ; do echo $i; done 1 2 A B Abc Пример перечисления в переменную файлов по "маске" для перекодирования видео: for i in *.avi; do
2. Подстановка результатов выполнения другой команды
for VAR in $(Пример использования результатов команды seq: for i in $(seq [КЛЮЧ]); do echo $i; done $ for i in $(seq 3); do echo $i; done 1 2 3 $ for i in $(seq 3 5); do echo $i; done 3 4 5 $ for i in $(seq 2 2 6); do echo $i; done 2 4 6 Пример использования результатов команды ls: $ for i in $(ls /$HOME/Video); do echo $i; done 001.avi 002.avi 003.avi
3. Подстановка используя Си-стиль (C-style)
for ((EXPR1; EXPR2; EXPR3)) do <список команд> done for ((i=1; i<=3 ; i++)); do echo $i; done $ for ((i=1; i<=3 ; i++)); do echo $i; done 1 2 3 Подробнее о применении C-style в Bash4. Перечисление при помощи фигурных скобок {..}
Применение синтаксиса {START..END} поддерживается начиная с bash version 3.0+ , а начиная с bash version 4.0+ поддерживается синтаксис {START..END..INCREMENT} :
for VAR in {5. Подстановка параметров (in "$@")
Выполняет команды для каждого параметра, который был передан сценарию. for VAR in $@ doТак если создать скрипт test.sh #!/bin/sh for VAR in $@ do echo $VAR done то при запуске его с параметрами: $ ./test.sh param1 param2 param3 param1 param2 param3 Часть in $@ можно опускать. Тогда скрипт test.sh перепишется: #!/bin/sh for VAR do echo $VAR done
Приведу пару примеров (с in и без): $ function FUNC_1 { for VAR in $@; do echo $VAR; done; } $ FUNC_1 param1 param2 param3 param1 param2 param3 $ function FUNC_2 { for VAR; do echo $VAR; done; } $ FUNC_2 param1 param2 param3 param1 param2 param3
6. Применение continue и break в цикле for
Для всех вышеперечисленных конструкций возможно использовать команды "continue" для перехода к следующему элементу цикла или "break" для выхода из цикла.Пример (завершить при i=6 и не выполнять при i=3 и i=5): for i in {1..8}; do if [ $i -eq 6 ]; then break; fi if [ $i -eq 3 ] || [ $i -eq 5 ]; then continue; fi echo $i done Результат выполнения: $ $ for i in {1..8}; do \ > if [ $i -eq 6 ]; then break; fi; \ > if [ $i -eq 3 ] || [ $i -eq 5 ]; then continue; fi; \ > echo $i; \ > done 1 2 4
Язык программирования shell имеет несколько конструкций, которые придадут гибкость вашим программам:
- комметнарии позволят описывать функции программы;
- "here document" позволяет вам включать в shell программы строки, которые будут перенаправляться как ввод в некоторые команды shell программы;
- команда exit позволяет завершать программу в нужной точке и использовать коды возврата;
- конструкции цикла for, while позволяют повторять группу команд в цикле;
- условные команды if и case выполняют группу команд, если выполнилось некоторое условие;
- команда break позволяет выполнить безусловный выход из цикла.
9.3.1. Комментарии
Чтобы в программе разместить комментарии, воспользуйтесь знаком #. Если знак # стоит после команды, то сама команда выполняется, а комментарий игнорируется. Формат строки комментария:
#comment
9.3.2. "Here document"
"Here document" позволяет размещать в shell программе строки, которые перенаправляются в качестве ввода команды в этой программе. Это один из способов обеспечения ввода для команды в shell программе без использования отдельного файла. Запись состоит из символа перенаправления << и разделителя, который указывает начало и конец строк ввода. В качестве разделителя может использоваться один символ или строка символов. Чаще всего это знак!.
Формат команды следующий:
Command<
9.3.3. Использование ed в shell программе
"Here document" предлагает способ использования ed в shell программе. Предположим вы хотите создать shell программу, которая будет вызывать редактор ed, проводить глобальные изменения в файле, записывать изменения в файл и затем завершать работу с ed. На следующем экране приведено содержание программы ch.text, которая выполняет эти задачи:
$ cat ch.text Обратите внимание на знак - (минус) в команде ed. Эта опция предотвращает распечатку счетчика символов на экране. Обратите также внимание на формат команды ed для глобальной замены: G/$old_text/s//$new_text/g
Программа использует 3 переменные: file1, old_text, new_text. При запуске эта программа использует команду read для получения значений этих переменных. Эти переменные содержат следующую информацию:
Переменные вводятся в программу, here document перенаправляет команду глобальной замены, команду записи и команду завершения команде ed. Запустите программу ch.text. Получите следующий экран: $ ch.text Большинство команд shell возвращает коды, которые указывают, успешно ли завершилась команда. Если возвращаемое значение 0(ноль), то команда выполнилась успешно. Коды возврата не печатаются автоматически, но их можно получить как значение специального параметра shell $?. После выполнения в интерактивном режиме команды, вы можете увидеть код завершения при вводе: Echo $?
Рассмотрим следующий пример:
$ cat hi
This is file hi.
$ echo $?
0
$ cat hello
cat: cannot open hello
$ echo $?
2
$
В первом случае файл hi существует в вашем справочнике и вы имеете разрешение на чтение. С помощью команды cat вы можете распечатать содержимое файла. Результат команды cat: код возврата 0, который вы получите, задав параметр $?. Во втором случае файл либо не существует, либо вы не имеете право на чтение. Команда cat печатает диагностическое сообщение и возвращает код 2. shell программа нормально завершается, когда выполнится последняя команда в файле. Однако вы можете использовать команду exit для завершения программы. Более важно то, что вы можете использовать команду exit для получения кодов возврата shell программы. Операторы цикла for и while позволяют выполнить команду или последовательность команд несколько раз. Оператор for выполняет последовательность команд для каждого элемента списка. Он имеет формат: For variable Для каждой итерации цикла следующий элемент списка присваивается переменной, данной в операторе for. Ссылка на эту переменную может быть сделана в любом месте в командах внутри оператора do. При конструировании каждой секции команд вам необходимо убедиться, что каждому do соответствует done в конце цикла. Переменная может иметь любое имя. Например, если ваша переменная названа var, то ссылка в списке команд на $var сделает значение доступным. Если оператор in опущен, то значением для var будет набор аргументов, заданный в команде и доступный в специальном параметре $*. Список команд между ключевым словом do и done будет выполнен для каждого значения. Когда команды будут выполнены для последнего элемента списка, программа будет выполнять строку ниже done. Оператор цикла while использует 2 группы команд. Он будет выполнять последовательность команд во второй группе (список do ... done) до тех пор пока последняя команда в первой группе (список while) возвращает состояние "истина", означающее, что выражение после do может быть выполнено. Общий формат оператора цикла while:
While Например, программа enter.name использует цикл while для ввода списка имен в файл. Программа состоит из следующих командных строк: $ cat enter.name Внеся некоторые добавления, получим следующую программу: $ cat enter.name Обратите внимание, что после завершения цикла программа выполняет команды ниже done. В первых двух командах echo используются специальные символы, так что вы должны воспользоваться кавычками для отмены специального значения. На следующем экране приведены результаты выполнения программы enter.name: $ enter.name После того, как цикл завершится, программа распечатает все имена, содержащиеся в xfile. Файловая система имеет файл /dev/null, где вы можете хранить нежелательный вывод. Например, если просто ввести команду who, то система ответит, кто работает в системе. Если вы перенаправите вывод этой команды в /dev/null: Who > /dev/null
то не получите ответа.
Команда if говорит shell программе, что нужно выполнить последовательность команд после then, если последняя команда в списке команд конструкции if выполнилась успешно. Конструкции if заканчиваются ключевым словом fi. Общий формат конструкции if:
If Например, shell программа search демонстрирует применение конструкции if ... then. Программа search использует команду grep для поиска слова в файле. Если grep выполнилась успешно, то программа отображает найденное слово. Экран будет выглядеть следующим образом: $ cat search Эта программа отображает вывод команды grep. Если вы хотите сохранить ответ системы на команду grep в вашей программе, то воспользуйтесь файлом /dev/null, изменив командную строку if на следующую: If grep $word $file > /dev/null Теперь выполните команду search. Она ответит только сообщением, указанным после команды echo. Конструкция if ... then ... else может исполнять альтернативный набор команд, стоящий после else, в случае, если последовательность if является ложью. Формат этой конструкции следующий: If С помощью этой конструкции вы можете усовершенствовать программу search, так что она будет сообщать вам и найденное слово и то, что слово не найдено. В этом случае программа search будет выглядеть следующим образом: $ cat search Команда test
Команда test используется для организации цикла. Она проверяет на истинность определенные условия и полезна для организации условных конструкций. Если условие истинно, то цикл будет продолжен. Если условие ложно, то цикл завершится и будет выполняться следующая команда. Некоторые примеры использования команды test:
test -r file Пример. Создадим shell программу, которая перемещает все исполняемые файлы из текущего справочника в ваш справочник bin. Для этого воспользуемся командой test -x для выбора исполняемых файлов. Программа mv.file будет выглядеть следующим образом: $ cat mv.file Конструкция case ... esac позволяет выбрать вам один из несколько шаблонов и затем выполнить список команд для этого шаблона. Выражение-шаблон должно начинаться с ключевого слова in, а правая круглая скобка должна быть помещена после последнего символа каждого шаблона. Последовательность команд для каждого шаблона заканчивается двумя знаками;;. Конструкция case должна быть закончена ключевым словом esac. Общий формат конструкции case:
Case word Конструкция case пытается найти word с шаблоном pattern в первой секции шаблонов. Если поиск удачен, то программа выполняет командные строки после первого шаблона до соответствующих знаков;;. Если первый шаблон не найден, то осуществляется переход ко второму шаблону. Если любой шаблон найден, то программа не рассматривает остальные шаблоны, а переходит к команде, следующей за esac. Знак * используется как шаблон для поиска любого word и таким образом дает вам набор команд, который будет выполнен, если никакой другой шаблон не будет найден. Поэтому шаблон звездочка (*) размещается как последний шаблон в конструкции case, чтобы другие шаблоны были проверены первыми. Это поможет вам обнаружить некорректный и неожиданный ввод. В шаблонах могут использоваться метасимволы *, ?, . Это обеспечивает гибкость программ. Рассмотрим пример. Программа set.term устанавливает переменную TERM в соответствии с типом терминала, который вы используете. Применяется следующая командная строка: TERM=terminal_name Шаблон * стоит последним в списке шаблонов. Он выдает предупреждающее сообщение, что для указанного типа терминала нет соответствующего шаблона и позволяет вам завершить конструкцию case. $ cat set.term Команда break безусловно останавливает выполнение любого цикла, в котором он встречается и передает управление команде, следующей после ключевых слов done, fi или esac. В предыдущем примере программы set.term вы можете использовать команду break, вместо echo, чтобы выйти из программы, как приведено в следующем примере: $ cat set.term Команда continue приведет к тому, что программа немедленно перейдет к следующей итерации цикла while или for без выполнения остальных команд в цикле. Основы BASH. Часть 2. Рассмотрим небольшой пример: Пример работы цикла рассмотрим на следующем примере: Echo "Do you wish to continue?" Как видим цикл выполняется до тех пор, пока мы не введем что-то отличное от «yes». Между do и done можно описывать любые структуры, операторы и т.п., все они будут выполнятся в цикле.Но следует быть осторожным с этим циклом, если вы запустите на выполнение в нём какую-либо команду, без изменения переменной выражения, вы можете попасть в бесконечный цикл. Рассмотрим еще один пример, я взял его из книги Advanced Bash Scripting. Уж очень он мне понравился:), но я его немного упростил. В этом примере мы познакомимся с еще одним типом циклов UNTIL-DO
. Эта практически полный аналог цикла WHILE-DO, только выполняется пока какое-то выражение ложно. Dnd=$dividend #мы будем изменять переменные dividend и divisor, Until [ "$remainder" -eq 0 ] Echo "НОД чисел $dnd и $dvs = $dividend" Let "c = a + b" #сложение Чаще всего скрипты на Bash используются в качестве автоматизации каких-то рутинных операций в консоли, отсюда иногда возникает необходимость в обработке stdout одной команды и передача на stdin другой команде, при этом результат выполнения одной команды должен быть неким образом обработан. В этом разделе я постораюсь объяснить основные принципы работы с внешними командами внутри скрипта. Думаю что примеров я привел достаточно и можно теперь писать только основные моменты. Результат работы: qwerty
Как видно, все не сложно, достаточно понять принцип и написать пару своих скриптов. В заключении статьи хочу пожелать удачи в изучении BASH и Linux в целом. Критика, как водится приветствуется. Следующая статья возможно будет посвещена использованию таких программ как sed, awk. Основы BASH. Часть 2. Рассмотрим небольшой пример: Пример работы цикла рассмотрим на следующем примере: Echo "Do you wish to continue?" Как видим цикл выполняется до тех пор, пока мы не введем что-то отличное от «yes». Между do и done можно описывать любые структуры, операторы и т.п., все они будут выполнятся в цикле.Но следует быть осторожным с этим циклом, если вы запустите на выполнение в нём какую-либо команду, без изменения переменной выражения, вы можете попасть в бесконечный цикл. Рассмотрим еще один пример, я взял его из книги Advanced Bash Scripting. Уж очень он мне понравился:), но я его немного упростил. В этом примере мы познакомимся с еще одним типом циклов UNTIL-DO
. Эта практически полный аналог цикла WHILE-DO, только выполняется пока какое-то выражение ложно. Dnd=$dividend #мы будем изменять переменные dividend и divisor, Until [ "$remainder" -eq 0 ] Echo "НОД чисел $dnd и $dvs = $dividend" Let "c = a + b" #сложение Чаще всего скрипты на Bash используются в качестве автоматизации каких-то рутинных операций в консоли, отсюда иногда возникает необходимость в обработке stdout одной команды и передача на stdin другой команде, при этом результат выполнения одной команды должен быть неким образом обработан. В этом разделе я постораюсь объяснить основные принципы работы с внешними командами внутри скрипта. Думаю что примеров я привел достаточно и можно теперь писать только основные моменты. Результат работы: qwerty
Как видно, все не сложно, достаточно понять принцип и написать пару своих скриптов. В заключении статьи хочу пожелать удачи в изучении BASH и Linux в целом. Критика, как водится приветствуется. Следующая статья возможно будет посвещена использованию таких программ как sed, awk. Командная оболочка в любых unix-подобных системах, к которым относится и GNU/Linux, является обычной программой, запускаемой как в текстовой консоли (которая используется всё реже), так и в графической среде – в окне эмулятора терминала, доступного в любой Linux-системе. Ее задача проста и очевидна: принять строку (или строки) ввода, произвести их синтаксический анализ и на основе результатов этого анализа отреагировать соответствующим образом – выполнить команду, запустить программу, вывести диагностическое сообщение и т.п. Почти во всех дистрибутивах Linux для пользователей по умолчанию назначается командная оболочка bash (Bourne Again SHell – ещё одна командная оболочка Бурна; Стив Бурн – автор первой командной оболочки в Unix – sh). Фактически она стала неофициальным стандартом, и усовершенствование ее функциональных возможностей продолжается непрерывно. Существуют и другие командные оболочки – tcsh (версия C-shell), ksh (Korn Shell), zsh и т.д. – у каждой есть свои достоинства и недостатки, а также свои группы поклонников. Тем не менее, bash более привычна широким массам пользователей с различными уровнями подготовки, потому я и остановил свой выбор на ней. Стоит также отметить, что какими бы возможностями ни обладали различные оболочки, все они совместимы со своим идеологическим прародителем – Bourn Shell (sh). Иными словами, скрипт, написанный для sh, будет корректно работать в любой современной оболочке (обратно, вообще говоря, неверно). Может возникнуть вопрос: зачем возиться с командной строкой, если существуют удобные и красивые графические интерфейсы? Тому есть множество причин. Во-первых, далеко не все операции удобнее и быстрее выполнять с помощью графического интерфейса. Во-вторых, каждая программа следует основополагающему принципу Unix-систем: делать чётко определённую работу и делать её хорошо. Иными словами, вы всегда понимаете, что происходит при запуске той или иной утилиты (если что-то не вполне понятно, то следует обратиться к man-руководству). В-третьих, осваивая команды, пробуя их сочетания и комбинации их параметров, пользователь изучает систему, приобретая ценный практический опыт. Вы получаете доступ к таким эффективным инструментам, как конвейеры, позволяющие организовать цепочку команд для обработки данных, средства перенаправления ввода/вывода, а кроме того, можете программировать непосредственно в командной оболочке. Пожалуй, на программировании стоит остановиться подробнее, тем более что многие системные сценарии в Linux (например, скрипты запуска системных сервисов) написаны для shell. Итак, командную оболочку можно рассматривать как язык программирования и как программную среду выполнения одновременно. Разумеется, этот язык не компилируемый, а интерпретируемый. Он допускает использование переменных: системных или собственных. Последовательность выполнения команд программы изменяется с помощью конструкций проверки условия и выбора соответствующего варианта: if-then-else и case. Циклы while, until и for позволяют автоматизировать многократно повторяющиеся действия. Имеется возможность объединять группы команд в логические блоки. Вы можете даже писать настоящие функции с передачей в них параметров. Таким образом, налицо все признаки и характеристики полноценного языка программирования. Попробуем извлечь из этого двойную пользу – наряду с изучением основ программирования автоматизируем свою повседневную работу. О необходимости регулярного резервного копирования данных знают все, но у пользователей вечно не хватает времени на эту скучную операцию. Выход прост – организовать автоматическое создание резервных копий. Это и будет нашим первым заданием по программированию в командной оболочке. Любой командный сценарий (script – скрипт, так называются программы командной оболочки) начинается со строки идентификатора, в которой явно задаётся интерпретатор команд с указанием полного пути к нему. Полный путь – последовательное перечисление всех каталогов, начиная с корневого, в которые надо войти, чтобы добраться до целевого файла, и, разумеется, имя этого файла. Запись полного пути чрезвычайно важна для однозначной идентификации каждого файла в иерархии файловой системы. Далее следуют четыре строки комментариев. Как только командная оболочка встречает символ "#", она считает все последующие символы комментариями и полностью игнорирует их до конца текущей строки. Поэтому комментарий можно начать не с самого начала строки, а сопроводить им какую-либо команду. После комментариев располагается пустая строка. Для командной оболочки она ничего не значит, и никаких действий не производится. В сценариях пустые строки обычно вставляют для того, чтобы обеспечить удобство чтения программного кода. Наконец-то мы добрались до первой «настоящей» команды. Она позволяет сменить каталог (Change Directory), т.е. перейти из текущего каталога в другой, переданный команде как аргумент. В большинстве случаев целевой каталог задаётся в явной форме, например, cd /tmp или cd projects, но в нашем случае используется предопределённая системная переменная HOME – в ней содержится полный путь к домашнему каталогу текущего пользователя, от имени которого выполняется командный сценарий. Тем самым мы избавляемся от необходимости вносить изменения в код всякий раз при смене пользователя, потому что команда возвращает любого в его личный каталог. Знак доллара "$" перед именем переменной означает, что необходимо извлечь значение, содержащееся в этой переменной, и подставить его в командную строку вместо её имени. Особо следует отметить, что в командном языке оболочки регистров букв имеют важное значение, т.е. HOME, Home и home – это три различные переменные. По соглашению, буквами верхнего регистра обозначаются имена системных переменных: HOME, PATH, EDITOR и т.д. Это соглашение не запрещает пользователям создавать свои переменные с именами из заглавных букв, но зачем усложнять себе жизнь, нарушая общепринятые нормы и правила? Не рекомендуется также изменять значения системных переменных без крайней необходимости. В общем, соблюдаем простое правило: системные переменные используем только для чтения, а если потребовалась собственная, то её имя записываем буквами нижнего регистра. Нашу первую команду можно было бы записать более кратко: Здесь символ "~" также означает домашний каталог текущего пользователя. Ветераны командной строки выражаются ещё лаконичнее: Смысл в том, что когда для команды cd не задан никакой аргумент, она выполняет переход в домашний каталог. На очереди классическая программная конструкция проверки условия и принятия соответствующего решения. Общая схема такова: Последнее слово конструкции (if в обратном порядке) выполняет роль закрывающей скобки, т.е. границы списка команд, выполняемых при истинности условия. Присутствие fi обязательно, даже если в списке лишь одна команда. Для проверки условия, как правило, применяется команда test или её альтернативная форма записи в квадратных скобках. Иначе говоря, записи абсолютно равнозначны. Я предпочитаю квадратные скобки, поскольку они более наглядно определяют границы проверяемого условия. И правая, и левая скобка должны быть обязательно отделены от условия пробелами. Критерии проверки условия определяются разнообразными флагами. Команда test распознаёт очень большой их список. В нашем примере использован флаг -d, позволяющий проверить, соответствует ли заданное после флага имя реально существующему каталогу (directory). Наиболее часто при работе с файлами применяются следующие флаги: F – существует ли обычный файл с заданным именем; R – установлено ли для заданного файла право на чтение из него; W – установлено ли для заданного файла право на запись в него; X – установлено ли для заданного файла право на его выполнение; S – имеет ли заданный файл ненулевой размер. В нашем случае перед условием стоит восклицательный знак, обозначающий операцию логического отрицания, поэтому смысл проверяемого условия становится абсолютно противоположным. Попробуем записать смысл этих команд на обычном русском языке: Как видите, всё оказалось не таким уж и сложным. Немного практики, и вы без труда сможете читать и самостоятельно создавать подобные конструкции. Команда создания каталога настолько очевидна, что дополнительных разъяснений не требуется. В следующей строке мы создаём собственную локальную переменную cur_date. В подавляющем большинстве случаев переменные создаются простым присваиванием конкретного значения, например: Но в нашем примере применяется небольшая хитрость. Обратите внимание, что после знака равенства – символа присваивания – записана команда в обратных кавычках. Такая форма записи позволяет присвоить переменной не саму строку, а результат её выполнения. Здесь это вывод команды date, которая возвращает текущую дату и время в формате, определяемом списком параметров: %Y – текущий год в полной форме, т.е. из четырёх цифр (например, 2009); %m – номер текущего месяца (например, 09 – для сентября); %d – номер текущего дня; %H – текущий час в 24-часовом формате; %M – текущая минута. Таким образом, если выполнить команду десятого сентября 2009 года в 22:45, то переменной cur_date будет присвоено строковое значение "200909102245". Цель этого ухищрения – сформировать уникальное, не повторяющееся имя архивного файла. Если вы намерены запустить несколько экземпляров программы в течение одной минуты, то можете улучшить уникальность имён, добавляя ещё и текущие секунды. Как? Изучите руководство утилиты date (man date) – в этом нет ничего сложного. Прежде чем приступить к созданию файла архива, необходимо определить, какие именно каталоги мы будем сохранять в нём. Для большей гибкости можно задать набор каталогов, архивируемых по умолчанию, но предусмотреть возможность замены этого набора списком каталогов, передаваемым как аргумент в наш командный сценарий. Для этого используются специальные переменные командной оболочки: $# – число переданных в сценарий параметров и $* – все переданные параметры, записанные в формате одной строки. Проверка условия «если число переданных параметров равно нулю», то выполнить следующую команду. Отметим, что ключевое слово then можно записать в строке условия, отделив его от условного выражения точкой с запятой. Команда создания архивного файла и сжатия этого файла. Сама утилита tar не выполняет сжатие, а только лишь собирает все заданные файлы и каталоги в единый tar-файл. Для этого предназначен первый флаг - c (create – создать). Сжатие выполняет внешняя программа – здесь это gzip, вызываемый вторым флагом - z. Если в вашей системе установлена более эффективная программа сжатия bzip2, то вы можете воспользоваться ею, изменив команду следующим образом: Третий флаг f сообщает о том, что далее следует имя архивного файла, поэтому всегда является замыкающим в перечне флагов. Обратите внимание на то, что при подстановке имя переменной заключено в фигурные скобки. Это сделано, чтобы явно выделить переменную в окружающей её строке, тем самым устраняя многие потенциальные проблемы. Расширения архивному файлу не присваиваются автоматически, вы сами дописываете всё необходимое. В качестве каталогов, архивируемых по умолчанию, я указал projects и bin, но вы можете записать здесь имена своих наиболее ценных каталогов. Ключевое слово else открывает альтернативную ветвь выполнения. Команды этого блока начинают работать, если проверка условия даёт результат «ложь» (в нашем примере: «число переданных параметров ненулевое», т.е. пользователь задал имена каталогов). В этом случае команда будет выглядеть так: Здесь каталоги по умолчанию заменены строкой имён каталогов, принятой извне. Имеется возможность принимать и обрабатывать каждый внешний параметр по отдельности, но нам удобнее передать строку целиком. В конце программы выполняется ещё одна проверка. В unix-средах все команды возвращают код статуса завершения своей работы. Если команда отработала успешно, то она возвращает код 0, в противном случае код завершения будет ненулевым. Чтобы проверить успешность выполнения предыдущей команды архивации, воспользуемся ещё одной специальной переменной $?, в которой всегда содержится значение кода завершения самой последней команды. Если в переменной $? содержится 0, т.е. файл резервной копии был успешно создан, то мы перемещаем его в каталог архивов: и выдаём соответствующее сообщение: Если проверка показала, что код завершения операции архивирования не равен нулю, то выводится сообщение об ошибке: На этом работа нашего командного сценария завершается. Чтобы проверить работу нашей программы, необходимо сохранить описанный выше исходный код в файле, например, с именем bckp, а затем для удобства сделать его выполняемым: и запустить: для создания резервной копии каталогов, заданных по умолчанию, и для создания резервной копии перечисленных каталогов (укажите имена каталогов, действительно существующих в вашей системе, иначе получите сообщение об ошибке). Можно поместить файл bckp в один из каталогов, указанных в системной переменной PATH. Наиболее предпочтительными местами размещения являются /usr/local/bin или $HOME/bin, если таковые у вас имеются. После этого вы можете запускать bckp как системную команду. Несколько слов об автоматизации резервного копирования. Для этой цели служит системный планировщик cron, который считывает рабочие инструкции из специального crontab-файла. Чтобы определить такие инструкции, необходимо создать и отредактировать свой crontab-файл при помощи команды: Инструкции записываются в строго определённом формате (поля разделяются пробелами): Один из вариантов расписания операций резервного копирования может выглядеть следующим образом: Это означает, что сценарий резервного копирования (следует указать полный путь к этому файлу) будет выполняться в 23:30 10-го, 20-го и 30-го числа каждого месяца независимо от дня недели. (Звёздочки обозначают весь допустимый диапазон значений, в данном случае: каждый месяц – в 4-м поле, любой день недели – в 5-м поле) Если вы предпочитаете подводить итоги по неделям, а ваша система работает круглосуточно, то имеет смысл запланировать резервное копирование в часы с минимальной нагрузкой: Здесь резервные копии будут создаваться в 5:00 по средам и пятницам в каждом месяце (звёздочка в 4-м поле), независимо от числа (звёздочка в 3-м поле). Обо всех тонкостях составления расписания можно прочитать в руководстве man 5 crontab. Рассмотренный в данной статье сценарий резервного копирования обладает скромными функциональными свойствами. Но не в этом состояла его главная задача, а в том, чтобы читатель понял, что можно делать в командной строке, и не только скопировал и выполнил предложенный командный файл, а заинтересовался расширением его функций, занялся исследованием необъятных возможностей, предоставляемых командными оболочками. И если кто-то, прочитав эту статью, попробует усовершенствовать приведённый здесь код, или напишет собственный вариант, или реализует свою независимую идею, то я сочту, что основная цель достигнута. static.content.url=http://www.сайт/developerworks/js/artrating/ ArticleID=458335 ArticleTitle=Основы программирования в командной оболочке shell
file - имя файла, который будет редактироваться;
old_text - текст, который будет изменен;
new_text - новый текст.9.3.4. Коды завершения
9.3.4.1. Проверка кодов завершения
9.3.5. Циклы
9.3.5.1. Оператор for
9.3.5.2. Оператор while
9.3.6. Использование /dev/null
9.3.7. Условные операторы
Оператор if ... then
9.3.8. Безусловная передача управления
Извиняюсь за такую большую задержку между статьями, но сессия дает о себе знать в самый неподходящий момент:)
Всем спасибо за замечания, критику и дополнения, которые были озвучены в комментариях к прошлой статье .
Эта часть, как и обещал, будет посвящена циклам, математическим операциям и использованию внешних команд.
Начнем.Циклы. Цикл for-in.
Оператор for-in предназначен для поочередного обращения к значениям перечисленным в списке. Каждое значение поочередно в списке присваивается переменной.
Синтаксис следующий:
for переменная in список_значений
do
команды
done #!/bin/bash
for i in 0 1 2 3 4 #переменной $i будем поочередно присваивать значения от 0 до 4 включительно
do
echo "Console number is $i" >> /dev/pts/$i #Пишем в файл /dev/pts/$i(файл виртуального терминала) строку "Console number is $i"
done #цикл окончен
exit 0
После выполнения примера в первых 5 виртуальных консолях(терминалах) появится строка с её номером. В переменную $i поочередно подставляются значения из списка и в цикле идет работа со значением этой переменнойЦиклы. Цикл while.
Цикл while сложнее цикла for-in и используется для повторения команд, пока какое-то выражение истинно(код возврата = 0).
Синтаксис оператора следующий:
while выражение или команда возвращающая код возврата
do
команды
done #!/bin/bash
again=yes #присваиваем значение "yes" переменной again
while [ "$again" = "yes" ] #Будем выполнять цикл, пока $again будет равно "yes"
do
echo "Please enter a name:"
read name
echo "The name you entered is $name"
read again
done
echo "Bye-Bye"
А теперь результат работы скрипта: ite@ite-desktop:~$ ./bash2_primer1.sh
Please enter a name:
ite
The name you entered is ite
Do you wish to continue?
yes
Please enter a name:
mihail
The name you entered is mihail
Do you wish to continue?
no
Bye-Bye
Теперь об условии истинности. После while, как и в условном операторе if-then-else можно вставлять любое выражение или команду, которая возвращает код возврата, и цикл будет исполнятся до тех пор, пока код возврата = 0! Оператор "[" аналог команды test, которая проверяет истинность условия, которое ей передали.
Вот пример: #!/bin/bash
echo "Введите числитель: "
read dividend
echo "Введите знаменатель: "
read divisor
#сохраним их знания в других переменных, т.к. они нам
#понадобятся
dvs=$divisor
remainder=1
do
let "remainder = dividend % divisor"
dividend=$divisor
divisor=$remainder
done
Результат выполнения скрипта: ite@ite-desktop:~$ ./bash2_primer3.sh
Введите числитель:
100
Введите знаменатель:
90
НОД чисел 100 и 90 = 10Математические операции
Команда let.
Команда let производит арифметические операции над числами и переменными.
Рассмотрим небольшой пример, в котором мы производим некоторые вычисления над введенными числами: #!/bin/bash
echo "Введите a: "
read a
echo "Введите b: "
read b
echo "a+b= $c"
let "c = a / b" #деление
echo "a/b= $c"
let "c <<= 2" #сдвигает c на 2 разряда влево
echo "c после сдвига на 2 разряда: $c"
let "c = a % b" # находит остаток от деления a на b
echo "$a / $b. остаток: $c "
Результат выполнения: ite@ite-desktop:~$ ./bash2_primer2.sh
Введите a:
123
Введите b:
12
a+b= 135
a/b= 10
c после сдвига на 2 разряда: 40
123 / 12. остаток: 3
Ну вот, как видите ничего сложного, список математических операций стандартный:
+ - сложение
- - вычитание
* - умножение
/ - деление
** - возведение в степень
% - модуль(деление по модулю), остаток от деления
let позволяет использовать сокращения арифметических команд, тем самым сокращая кол-во используемых переменных. Например: a = a+b эквивалентно a +=b и т.дРабота с внешними программами при написании shell-скриптов
Для начала немного полезной теории.Перенаправление потоков.
В bash(как и многих других оболочках) есть встроенные файловые дескрипторы: 0 (stdin), 1 (stdout), 2 (stderr).
stdout - Стандартный вывод. Сюда попадает все что выводят программы
stdin - Стандартный ввод. Это все что набирает юзер в консоли
stderr - Стандартный вывод ошибок.
Для операций с этими дескрипторами, существуют специальные символы: > (перенаправление вывода), < (перенаправление ввода). Оперировать ими не сложно. Например:
перенаправить вывод команды cat /dev/random в /dev/null (абсолютно бесполезная операция:))) или
записать в файл listing содержание текущего каталога (уже полезней)
Если есть необходимость дописывать в файл(при использовании ">" он заменятеся), необходимо вместо ">" использовать ">>"
после просьбы sudo ввести пароль, он возьмется из файла my_password, как будто вы его ввели с клавиатуры.
Если необходимо записать в файл только ошибки, которые могли возникнуть при работе программы, то можно использовать:./program_with_error 2> error_file
цифра 2 перед ">" означает что нужно перенаправлять все что попадет в дескриптор 2(stderr).
Если необходимо заставить stderr писать в stdout, то это можно можно след. образом:
символ "&" означает указатель на дескриптор 1(stdout)
(Поумолчанию stderr пишет на ту консоль, в котрой работает пользователь(вренее пишет на дисплей)).2.Конвееры.
Конвеер - очень мощный инструмент для работы с консолью Bash. Синтаксис простой:
команда1 | команда 2 - означает, что вывод команды 1 передастся на ввод команде 2
Конвееры можно группировать в цепочки и выводить с помощью перенаправления в файл, например:ls -la | grep «hash» |sort > sortilg_list
вывод команды ls -la передается команде grep, которая отбирает все строки, в которых встретится слово hash, и передает команде сортировке sort, которая пишет результат в файл sorting_list. Все довольно понятно и просто.1. Передача вывода в переменную.
Для того чтобы записать в переменную вывод какой-либо команды, достаточно заключить команду в `` ковычки, например a = `echo "qwerty"`
echo $a
Однако если вы захотите записать в переменную список директорий, то необходимо, должным образом обработать результат для помещения данных в переменную. Рассмотрим небольшой, пример: LIST=`find /svn/ -type d 2>/dev/null| awk "{FS="/"} {print $4}"| sort|uniq | tr "\n" " "`
for ONE_OF_LIST in $LIST
do
svnadmin hotcopy /svn/$ONE_OF_LIST /svn/temp4backup/$ONE_OF_LIST
done
Здесь мы используем цикл for-do-done для архивирование всех директорий в папке /svn/ с помощью команды svnadmin hotcopy(что в нашем случае не имеет никого значения, просто как пример). Наибольшй интерес вызывает строка: LIST=`find /svn/ -type d 2>/dev/null| awk "{FS="/"} {print $4}"| sort|uniq | tr "\n" " "` В ней переменной LIST присваивается выполнение команды find, обработанной командами awk, sort, uniq,tr(все эти команды мы рассматривать не будем, ибо это отдельная статья). В переменной LIST будут имена всех каталогов в папке /svn/ пгомещенных в одну строку(для того чтобы её стравить циклу.
Извиняюсь за такую большую задержку между статьями, но сессия дает о себе знать в самый неподходящий момент:)
Всем спасибо за замечания, критику и дополнения, которые были озвучены в комментариях к прошлой .
Эта часть, как и обещал, будет посвящена циклам, математическим операциям и использованию внешних команд.
Начнем.Циклы. Цикл for-in.
Оператор for-in предназначен для поочередного обращения к значениям перечисленным в списке. Каждое значение поочередно в списке присваивается переменной.
Синтаксис следующий:
for переменная in список_значений
do
команды
done #!/bin/bash
for i in 0 1 2 3 4 #переменной $i будем поочередно присваивать значения от 0 до 4 включительно
do
echo "Console number is $i" >> /dev/pts/$i #Пишем в файл /dev/pts/$i(файл виртуального терминала) строку "Console number is $i"
done #цикл окончен
exit 0
После выполнения примера в первых 5 виртуальных консолях(терминалах) появится строка с её номером. В переменную $i поочередно подставляются значения из списка и в цикле идет работа со значением этой переменнойЦиклы. Цикл while.
Цикл while сложнее цикла for-in и используется для повторения команд, пока какое-то выражение истинно(код возврата = 0).
Синтаксис оператора следующий:
while выражение или команда возвращающая код возврата
do
команды
done #!/bin/bash
again=yes #присваиваем значение "yes" переменной again
while [ "$again" = "yes" ] #Будем выполнять цикл, пока $again будет равно "yes"
do
echo "Please enter a name:"
read name
echo "The name you entered is $name"
read again
done
echo "Bye-Bye"
А теперь результат работы скрипта: ite@ite-desktop:~$ ./bash2_primer1.sh
Please enter a name:
ite
The name you entered is ite
Do you wish to continue?
yes
Please enter a name:
mihail
The name you entered is mihail
Do you wish to continue?
no
Bye-Bye
Теперь об условии истинности. После while, как и в условном операторе if-then-else можно вставлять любое выражение или команду, которая возвращает код возврата, и цикл будет исполнятся до тех пор, пока код возврата = 0! Оператор "[" аналог команды test, которая проверяет истинность условия, которое ей передали.
Вот пример: #!/bin/bash
echo "Введите числитель: "
read dividend
echo "Введите знаменатель: "
read divisor
#сохраним их знания в других переменных, т.к. они нам
#понадобятся
dvs=$divisor
remainder=1
do
let "remainder = dividend % divisor"
dividend=$divisor
divisor=$remainder
done
Результат выполнения скрипта: ite@ite-desktop:~$ ./bash2_primer3.sh
Введите числитель:
100
Введите знаменатель:
90
НОД чисел 100 и 90 = 10Математические операции
Команда let.
Команда let производит арифметические операции над числами и переменными.
Рассмотрим небольшой пример, в котором мы производим некоторые вычисления над введенными числами: #!/bin/bash
echo "Введите a: "
read a
echo "Введите b: "
read b
echo "a+b= $c"
let "c = a / b" #деление
echo "a/b= $c"
let "c <<= 2" #сдвигает c на 2 разряда влево
echo "c после сдвига на 2 разряда: $c"
let "c = a % b" # находит остаток от деления a на b
echo "$a / $b. остаток: $c "
Результат выполнения: ite@ite-desktop:~$ ./bash2_primer2.sh
Введите a:
123
Введите b:
12
a+b= 135
a/b= 10
c после сдвига на 2 разряда: 40
123 / 12. остаток: 3
Ну вот, как видите ничего сложного, список математических операций стандартный:
+ - сложение
- - вычитание
* - умножение
/ - деление
** - возведение в степень
% - модуль(деление по модулю), остаток от деления
let позволяет использовать сокращения арифметических команд, тем самым сокращая кол-во используемых переменных. Например: a = a+b эквивалентно a +=b и т.дРабота с внешними программами при написании shell-скриптов
Для начала немного полезной теории.Перенаправление потоков.
В bash(как и многих других оболочках) есть встроенные файловые дескрипторы: 0 (stdin), 1 (stdout), 2 (stderr).
stdout - Стандартный вывод. Сюда попадает все что выводят программы
stdin - Стандартный ввод. Это все что набирает юзер в консоли
stderr - Стандартный вывод ошибок.
Для операций с этими дескрипторами, существуют специальные символы: > (перенаправление вывода), < (перенаправление ввода). Оперировать ими не сложно. Например:
перенаправить вывод команды cat /dev/random в /dev/null (абсолютно бесполезная операция:))) или
записать в файл listing содержание текущего каталога (уже полезней)
Если есть необходимость дописывать в файл(при использовании ">" он заменятеся), необходимо вместо ">" использовать ">>"
после просьбы sudo ввести пароль, он возьмется из файла my_password, как будто вы его ввели с клавиатуры.
Если необходимо записать в файл только ошибки, которые могли возникнуть при работе программы, то можно использовать:./program_with_error 2> error_file
цифра 2 перед ">" означает что нужно перенаправлять все что попадет в дескриптор 2(stderr).
Если необходимо заставить stderr писать в stdout, то это можно можно след. образом:
символ "&" означает указатель на дескриптор 1(stdout)
(Поумолчанию stderr пишет на ту консоль, в котрой работает пользователь(вренее пишет на дисплей)).2.Конвееры.
Конвеер - очень мощный инструмент для работы с консолью Bash. Синтаксис простой:
команда1 | команда 2 - означает, что вывод команды 1 передастся на ввод команде 2
Конвееры можно группировать в цепочки и выводить с помощью перенаправления в файл, например:ls -la | grep «hash» |sort > sortilg_list
вывод команды ls -la передается команде grep, которая отбирает все строки, в которых встретится слово hash, и передает команде сортировке sort, которая пишет результат в файл sorting_list. Все довольно понятно и просто.1. Передача вывода в переменную.
Для того чтобы записать в переменную вывод какой-либо команды, достаточно заключить команду в `` ковычки, например a = `echo "qwerty"`
echo $a
Однако если вы захотите записать в переменную список директорий, то необходимо, должным образом обработать результат для помещения данных в переменную. Рассмотрим небольшой, пример: LIST=`find /svn/ -type d 2>/dev/null| awk "{FS="/"} {print $4}"| sort|uniq | tr "\n" " "`
for ONE_OF_LIST in $LIST
do
svnadmin hotcopy /svn/$ONE_OF_LIST /svn/temp4backup/$ONE_OF_LIST
done
Здесь мы используем цикл for-do-done для архивирование всех директорий в папке /svn/ с помощью команды svnadmin hotcopy(что в нашем случае не имеет никого значения, просто как пример). Наибольшй интерес вызывает строка: LIST=`find /svn/ -type d 2>/dev/null| awk "{FS="/"} {print $4}"| sort|uniq | tr "\n" " "` В ней переменной LIST присваивается выполнение команды find, обработанной командами awk, sort, uniq,tr(все эти команды мы рассматривать не будем, ибо это отдельная статья). В переменной LIST будут имена всех каталогов в папке /svn/ пгомещенных в одну строку(для того чтобы её стравить циклу.Что такое shell и зачем он нужен
Преимущества командной строки
Командная оболочка в качестве языка программирования
Hello, World! Простая система резервного копирования
Как автоматизировать операции резервного копирования «по расписанию»
Итоги и выводы
Ресурсы для скачивания