Сайт о телевидении

Сайт о телевидении

» » Shell как язык программирования и интегратор. Основы программирования в командной оболочке shell

Shell как язык программирования и интегратор. Основы программирования в командной оболочке shell

Язык программирования 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< ...input lines... delimiter

9.3.3. Использование ed в shell программе

"Here document" предлагает способ использования ed в shell программе. Предположим вы хотите создать shell программу, которая будет вызывать редактор ed, проводить глобальные изменения в файле, записывать изменения в файл и затем завершать работу с ed. На следующем экране приведено содержание программы ch.text, которая выполняет эти задачи:

$ cat ch.text echo Type in the filename read file1 echo Type in the exact text to be changed. read old_text echo Type in the exact new text to replace the above. read new_text ed - $file1 <

Обратите внимание на знак - (минус) в команде ed. Эта опция предотвращает распечатку счетчика символов на экране. Обратите также внимание на формат команды ed для глобальной замены:

G/$old_text/s//$new_text/g

Программа использует 3 переменные: file1, old_text, new_text. При запуске эта программа использует команду read для получения значений этих переменных. Эти переменные содержат следующую информацию:
file - имя файла, который будет редактироваться;
old_text - текст, который будет изменен;
new_text - новый текст.

Переменные вводятся в программу, here document перенаправляет команду глобальной замены, команду записи и команду завершения команде ed. Запустите программу ch.text. Получите следующий экран:

$ ch.text Type in the filename memo Type in the exact text to be changed. Dear John: Type in the exact new text to replace the above. To what it may concern: $ cat memo To what it may concern: $

9.3.4. Коды завершения

Большинство команд shell возвращает коды, которые указывают, успешно ли завершилась команда. Если возвращаемое значение 0(ноль), то команда выполнилась успешно. Коды возврата не печатаются автоматически, но их можно получить как значение специального параметра shell $?.

9.3.4.1. Проверка кодов завершения

После выполнения в интерактивном режиме команды, вы можете увидеть код завершения при вводе:

Рассмотрим следующий пример:

$ 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 программы.

9.3.5. Циклы

Операторы цикла for и while позволяют выполнить команду или последовательность команд несколько раз.

9.3.5.1. Оператор for

Оператор for выполняет последовательность команд для каждого элемента списка. Он имеет формат:

For variable in a_list_of_values do command_1 command_2 . . . last command done

Для каждой итерации цикла следующий элемент списка присваивается переменной, данной в операторе for. Ссылка на эту переменную может быть сделана в любом месте в командах внутри оператора do. При конструировании каждой секции команд вам необходимо убедиться, что каждому do соответствует done в конце цикла.

Переменная может иметь любое имя. Например, если ваша переменная названа var, то ссылка в списке команд на $var сделает значение доступным. Если оператор in опущен, то значением для var будет набор аргументов, заданный в команде и доступный в специальном параметре $*. Список команд между ключевым словом do и done будет выполнен для каждого значения.

Когда команды будут выполнены для последнего элемента списка, программа будет выполнять строку ниже done.

9.3.5.2. Оператор while

Оператор цикла while использует 2 группы команд. Он будет выполнять последовательность команд во второй группе (список do ... done) до тех пор пока последняя команда в первой группе (список while) возвращает состояние "истина", означающее, что выражение после do может быть выполнено.

Общий формат оператора цикла while:

While command_1 . . . last command do command_1 . . . last command done

Например, программа enter.name использует цикл while для ввода списка имен в файл. Программа состоит из следующих командных строк:

$ cat enter.name while read x do echo $x>>xfile done $

Внеся некоторые добавления, получим следующую программу:

$ cat enter.name echo Please type in each person"s name and than a echo Please end the list of names with a <^d> while read x do echo $x>>xfile done echo xfile contains the following names: cat xfile $

Обратите внимание, что после завершения цикла программа выполняет команды ниже done.

В первых двух командах echo используются специальные символы, так что вы должны воспользоваться кавычками для отмены специального значения. На следующем экране приведены результаты выполнения программы enter.name:

$ enter.name Please type in each person"s name and than a Please end the list of names with a <^d> Mary Lou Janice <^d> xfile contains the following names: Mary Lou Janice $

После того, как цикл завершится, программа распечатает все имена, содержащиеся в xfile.

9.3.6. Использование /dev/null

Файловая система имеет файл /dev/null, где вы можете хранить нежелательный вывод. Например, если просто ввести команду who, то система ответит, кто работает в системе. Если вы перенаправите вывод этой команды в /dev/null:

Who > /dev/null

то не получите ответа.

9.3.7. Условные операторы

Оператор if ... then

Команда if говорит shell программе, что нужно выполнить последовательность команд после then, если последняя команда в списке команд конструкции if выполнилась успешно. Конструкции if заканчиваются ключевым словом fi.

Общий формат конструкции if:

If command_1 . . . last command then command_1 . . . last command fi

Например, shell программа search демонстрирует применение конструкции if ... then. Программа search использует команду grep для поиска слова в файле. Если grep выполнилась успешно, то программа отображает найденное слово. Экран будет выглядеть следующим образом:

$ cat search echo Type in the word and the file name. read word file if grep $word $file then echo $word is in $file fi $

Эта программа отображает вывод команды grep. Если вы хотите сохранить ответ системы на команду grep в вашей программе, то воспользуйтесь файлом /dev/null, изменив командную строку if на следующую:

If grep $word $file > /dev/null

Теперь выполните команду search. Она ответит только сообщением, указанным после команды echo.

Конструкция if ... then ... else может исполнять альтернативный набор команд, стоящий после else, в случае, если последовательность if является ложью. Формат этой конструкции следующий:

If command_1 . . . last command .linthen command_1 . . . last command else command_1 . . . last command fi

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

$ cat search echo Type in the word and the file name. read word file if grep $word $file > /dev/null then echo $word is in $file else echo $word is NOT in $file fi $

Команда test

Команда test используется для организации цикла. Она проверяет на истинность определенные условия и полезна для организации условных конструкций. Если условие истинно, то цикл будет продолжен. Если условие ложно, то цикл завершится и будет выполняться следующая команда. Некоторые примеры использования команды test:

Test -r file истина, если файл существует и доступен для чтения; test -w file истина, если файл существует и доступен для записи; test -x file истина, если файл существует и является выполняемым; test -s file истина, если файл существует и имеет как минимум один символ; test var1 -eq var2 истина, если var1 равно var2; test var1 -ne var2 истина, если var1 не равно var2.

Пример. Создадим shell программу, которая перемещает все исполняемые файлы из текущего справочника в ваш справочник bin. Для этого воспользуемся командой test -x для выбора исполняемых файлов. Программа mv.file будет выглядеть следующим образом:

$ cat mv.file echo type in the directory path read path for file do if test -x $file then mv $file $path/$file fi done $

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

Общий формат конструкции case:

Case word in pattern1) command line 1 . . . last command line ;; pattern2) command line 1 . . last command line ;; pattern3) command line 1 . . last command line ;; *) command line 1 . . last command line ;; esac

Конструкция case пытается найти word с шаблоном pattern в первой секции шаблонов. Если поиск удачен, то программа выполняет командные строки после первого шаблона до соответствующих знаков;;.

Если первый шаблон не найден, то осуществляется переход ко второму шаблону. Если любой шаблон найден, то программа не рассматривает остальные шаблоны, а переходит к команде, следующей за esac. Знак * используется как шаблон для поиска любого word и таким образом дает вам набор команд, который будет выполнен, если никакой другой шаблон не будет найден. Поэтому шаблон звездочка (*) размещается как последний шаблон в конструкции case, чтобы другие шаблоны были проверены первыми. Это поможет вам обнаружить некорректный и неожиданный ввод.

В шаблонах могут использоваться метасимволы *, ?, . Это обеспечивает гибкость программ.

Рассмотрим пример. Программа set.term устанавливает переменную TERM в соответствии с типом терминала, который вы используете. Применяется следующая командная строка:

TERM=terminal_name

Шаблон * стоит последним в списке шаблонов. Он выдает предупреждающее сообщение, что для указанного типа терминала нет соответствующего шаблона и позволяет вам завершить конструкцию case.

$ cat set.term echo If you have a TTY 4420 type in 4420 echo If you have a TTY 5410 type in 5410 echo If you have a TTY 5420 type in 5420 read term case term in 4420) TERM-T4 ;; 5410) TERM-T5 ;; 5420) TERM-T7 ;; *) echo not a correcr terminal type ;; esac export TERM echo end of programm $

9.3.8. Безусловная передача управления

Команда break безусловно останавливает выполнение любого цикла, в котором он встречается и передает управление команде, следующей после ключевых слов done, fi или esac.

В предыдущем примере программы set.term вы можете использовать команду break, вместо echo, чтобы выйти из программы, как приведено в следующем примере:

$ cat set.term echo If you have a TTY 4420 type in 4420 echo If you have a TTY 5410 type in 5410 echo If you have a TTY 5420 type in 5420 read term case term in 4420) TERM-T4 ;; 5410) TERM-T5 ;; 5420) TERM-T7 ;; *) break ;; esac export TERM echo end of programm $

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

МОСКВА 2007

Лабораторный практикум по курсу: “Операционная система Red Hat Linux

Лабораторная работа №5

Программирование в SHELL

Цель работы : на основе ранее полученных навыков работы с командным интерпретатором BASH овладеть начальными навыками программирования в командном интерпретаторе BASH для создания файлов сценария – SHELL скриптов.

Теоретические сведения

Выполнение отдельных команд в командном интерпретаторе не всегда является эффективным средством работы с SHELL оболочкой. Довольно часто требуется выполнять одни и те же последовательности действий при работе с операционной системой Linux каждый месяц, каждую неделю, каждый день и иногда и несколько раз в день. Например, предположим, вы работаете на фирме тестером программного обеспечения (Test Manager). Каждый день вам требуется в командной оболочке Linux выполнять один тот набор действий, а именно: монтирование устройства CD-ROM; копирование всей информации с него в папку, скажем, /opt/program на жестком диске; демонтирование CD-ROM; чтение файла readme из этой папки; установка программы с жесткого диска из папки /opt/program; создания нового файла отчета в директории /home/user/report_program удаление всего содержимого дистрибутива с жесткого диска. И это притом, что основная ваша работа заключается в тестировании программного обеспечения на предмет выявления недоработок (bags). Задача на первый взгляд простая, но выполнять подобные действия по несколько раз в день, притом, что вы занимаетесь и другими делами, неудобно. Или, например, вы работаете в фирме системным администратором и обслуживаете около 50 компьютеров. Каждый день вам требуется раскопировать на все компьютеры один и тот же файл с инструкциями на текущий день директора фирмы для всех подчиненных. Кроме того, в ваши задачи также входит в конце рабочего дня сохранить все данные каждого пользователя на общем сервере фирмы с персональных компьютеров подчиненных. Задача также на первый взгляд простая, но работа по набору команд в командном интерпретаторе для 50 компьютеров займет много времени. А если к тому же вы при наборе будите ошибаться, например, от усталости? Данные для директора и их владельца очень важны, и потерять их Вам никак нельзя. Но это еще простые действия. А представьте, что названия файлов отчетов, название папок с данными, имена компьютеров каждый раз будут меняться? Что тогда делать? Выход один – написать файл-сценария , т.е. создать текстовый файл, в котором требуется описать всю последовательность команд с путями, опциями, аргументами, выражениями, действиями и так далее для выполнения определенного сценария. Например, резервирования данных. После ввода команд в текстовый файл-сценария, данный файл делают исполняемым или выполняют его специальных операторов выполнения командного интерпретатора. Использование файлов сценария является особенно эффективным, если вам очень часто требуется выполнять последовательность из большого числа команд. Также является эффективным средством, если в зависимости от результатов выполнения предыдущих команд зависит выполнение следующих. С помощью файлов-сценариев можно также использовать арифметические и логические выражения, создавать циклы, обеспечивающие многократное выполнение группы команд Linux.

Создание файлов-сценария. Создания сценариев представляет собой последовательный набор команд, операторов командного интерпретатора и некоторых других символов в текстовом файле. Файлы-сценария также называют скриптами, а командные интерпретаторы латинским названием SHELL. В связи с тем, что на сегодняшний день существуют разные командные интерпретаторы, написание файла-сценария с использованием дополнительных символов, например, метасимволов, совместно с командами не должно противоречить правилам синтаксиса выбранного командного интерпретатора, в котором предполагается выполнять данный скрипт. Процесс написания таких файлов называют SHELL программированием. Рассмотрим процесс программирования на примере интерпретатора BASH. Таким образом, скрипты и правила написания скриптов в данной лабораторной работе могут быть не переносимы на другие интерпретаторы, например, такие как С Shell или TC Shell.

Последовательность #!. Написание любого скрипта начинается с принадлежности его к одному из командных интерпретаторов. В первой строке скрипта обычно пишут последовательность #! , которая указывает системе, какой интерпретатор должен выполнить команды из данного сценария. Если первый символ пробел, считается, что сценарий написан для BASH или PDKSH. Если сценарий начинается только с символа # , то для его выполнения необходим TC Shell. Если же за символом # следует символ!, ядро запустит интерпретатор, путь которого указан далее в этой строке. Например, для BASH будет следующая запись: #!/bin/sh . Пробела или одиночного символа # в начале сценария достаточно для интерпретаторов BASH Shell и TC Shell только при условии, что они будут считывать свой сценарий. Чтобы один интерпретатор распознал сценарии другого, необходимо включать в сценарий символы #! , после чего указывается путь интерпретирующей программы. Тогда при вызове сценария будет прекращена работа текущего интерпретатора, вместо него будет загружен сценарий другого типа, а затем выполнен сценарий. Рекомендуется всегда начинать все сценарии с последовательности #! . Также строки, начинающиеся с символа # можно использовать для комментариев действий пользователя в скрипте. Встретив символ #, интерпретатор shell игнорирует эту строку. Каждый комментарий должен завершаться символом окончания строки. Использование комментариев является признаком хорошего тона.

Расширение и запуск скриптов. Обычно файлы-сценариев имеют не только имена, но также и расширения. Чаще всего в качестве расширений используют комбинацию букв sh от латинского слова shell. По такому расширению, не открывая файл, сразу понятно, что это shell скрипт, так как нам опять же понятно, что файл с расширением . c скорее всего является входным файлом языков высокого уровня С и С++. После набора содержимого файла, файл сохраняется. Запустить файл можно двумя способами либо сделать его исполняемым с помощью команды chmod, либо запускать его с помощью специальных операторов командного интерпретатора: sh и. Обычно пользователи задают для файл-сценария восьмеричные значения 750 или 550. В следующем примере сделаем скрипт script.sh выполняемым с помощью команды chmod и запустим его на выполнение из текущей директории в фоновом режиме.

chmod u+x script.sh

./ script.sh &

Теперь вернем файлу предыдущие атрибуты и запустим его на выполнение с помощью оператора BASH.

chmod u-x script.sh

sh script.sh&

Команда echo . Помимо перечня стандартных команд Linux, самое простое, что можно использовать в скрипте – это вывод текстовых комментариев пользователю с помощью команда echo. Например, данную команду можно использоваться для приглашения пользователя выполнить какое-нибудь действие или использовать для приветствия пользователя. В следующем примере с помощью echo отображается приветствие.

echo “Добрый день!”

Команда read . При создании скриптов вы можете также применять переменные и сценарии, написанные для других интерпретаторов и команд. Команда read служит командой запроса пользователя на ввод информации. Она сочетается с подсказкой пользователю, которая приглашает ввести нужную информацию. Приведем пример использования read.

echo “Введите ваше имя: ”

read your _ name

echo “ Добрый день ,” your_name “!”

Данный скрипт усложнен по отношению к предыдущему. Здесь используется переменная your_name , значение которой потом применяется совместно с текстом.

Использование переменных. Как и языках программирования, в shell Вы также можете использовать переменные, присваивать значения переменным можно через оператор присваивания равно «=». Сначала вводится имя переменной, потом без пробела знак «=», затем без пробела значение переменной. Имя переменной может состоять из любого количества буквенных символов, включая символ подчеркивания. Имя может содержать и цифры, однако не должно начинаться с цифры. Все остальные символы (в частности, восклицательный знак, амперсанд и пробел) в имя входить не должны. Такие символы зарезервированы интерпретатором для специальных целей. Как следствие, имя может состоять только из одного слова, поскольку при синтаксическом анализе команд интерпретатор рассматривает пробел как разделитель имен команд и аргументов. Значение переменной может состоять из любой последовательности символов. В следующем примере присвоим переменной «ppp» значение «www123yyy».

ppp =” www 123 yyy

Если вы используете в качестве значения переменной строковое значение, используйте двойные кавычки. После присвоения значения вы можете пользоваться именем переменной для ссылки на это значение, например использовать его в качестве аргумента команд сценария. На значение переменной можно ссылаться посредством ее имени, которое предваряется оператором $. Знак доллара - это специальный оператор, который использует имя переменной для ссылки на ее значение, то есть фактически для ее вычисления. Теперь с помощью уже знакомой команды echo и переменной «ppp» можно отображать значение этой переменной.

echo $ppp

www123yyy

Аргументы командной строки. В сценарии, как и в командах Linux, можно использовать аргументы. Аргумент в сценарии обозначается оператором $ с указанием номера позиции в командной строке. Нумерация параметров начинается с единицы, а заканчивается девятью. Первый параметр задается переменной $1, второй - $2 и т. д. Аргумент $0 резерви­руется для имени shell-сценария, в качестве которого выступает первое слово, находя­щееся в командной строке. По умолчанию имеется возможность устанавливать 9 переменных с $1 до $9 . Если вво­дится несколько аргументов, можно отдельно обращаться к каждому из них по его номеру. В следующем примере в командной строке вводятся три аргумента. Предварительно создадим скрипт arguments с аргументами, а потом его выполним.

Обращаем ваше внимание, если вам требуется использовать аргумент(ы) из нескольких слов, вы должны в командной строке взять его (их) в двойные кавычки. Иногда требуется задать в сценарии точное количество аргументов, это можно выполнить с помощью аргумента $# . Параметр $* позволяет указать все аргументы в командной строке.

Переменная export. Иногда для разных файлов-сценария требуется воспользоваться определенной переменной, которая уже была определена. Переменные, которые вы определяете в интерпретаторе shell, являются локальными для него. В некотором смысле такая пе­ременная принадлежит своему интерпретатору. Непосредственно определить переменную для другого интерпретатора нельзя, однако можно экспортировать определение переменной из одного интерпретатора в другой с помощью команды export. Команда export содержит инструкцию для системы, в соответствии с которой для каждого вновь образованного shell будет определяться копия этой переменной. Каждый новый интерпретатор shell будет иметь собственную копию экспортированной переменной. В следующем примере определим переменную «rrr» и экспортируем ее для других интерпретаторов с помощью команды export.

Арифметические операции – команда let . Команда let - это команда интерпретатора BASH shell, обеспечивающая выпол­нение операций над арифметическими величинами. С помощью этой команды можно сравнивать числовые значения или выполнять над ними арифметические операции, такие как сложение или умножение. Формат команды: let значение1 оператор значение2. Приведем пример.

$ let 2*5

10

В арифметические выражения, использующие оператор let, можно включать и опе­раторы присваивания. В следующем примере результат умножения двух чисел присваи­вается переменной total.

$ let “total=2*5”

$ echo $total

10

$

Операторы сравнения часто используются для сравнения числовых значений в управ­ляющих конструкциях, таких как циклы и условные переходы. В следующем примере команды сценария file1 четырежды выводят на экран слово "Привет!". В данном случае для управления выходом из цикла используется оператор let "ttt <= 4", а для увеличения переменной цикла again на единицу - оператор let "ttt = ttt + 1". Обратите внимание на то, что при изменении переменной again ее вычислять не требуется.

File1

ttt=l

while let "ttt<= 4"

do

echo $ttt Привет!

let "ttt = ttt + 1"

done

Выполнение скрипта:

$ file1

Привет!

Привет!

Привет!

Кроме того, вы также можете использовать и другие арифметические операторы. В таблице 1 приведены арифметические операторы и операторы сравнения Bash Shell.

Таблица 1 - Операторы BASH shell

Арифметические операторы

Функции

Умножение

Сложение

Вычитание

Деление с остатком

Операторы сравнения

Функции

Больше чем

Меньше чем

Больше либо равно

Меньше либо равно

Равенство в выражениях

Равенство в команде let

Не равно

Логическое И

Логическое ИЛИ

Логическое НЕ

Управляющие конструкции. Управляющие конструкции предназначены для управления ходом выполнения команд shell-сценария. Эти конструкции позволяют организовать повторное выполнение определенной последовательности команд или выбирать для выполнения команды, необходимые в конкретной ситуации. Управляющая конструкция состоит из двух основ­ных компонентов: операции проверки и команд. В результате выполнения сравнения (проверки условия) возвращается значение «истина» или «ложь», а затем на основании полученного результата выполняются определенные команды. Существует два вида управляющих конструкций: циклические (циклы) и условные (ус ловия). Циклическая конструкция используется для повторного выполнения команд, тогда как условная - для выполнения последовательности команд., которая удовлетво­ряет определенным условиям. В интерпретаторе BASH shell можно использовать три циклические конструкции, while, for и for-in, и две условные - if и case.

Управляющие конструкции while и if - это конструкции общего назначения, которые обычно используются при решении таких задач, как итерационные вычисления и проверка различных условий. Управляющие конструкции case и for ориентированы на более узкий круг задач. Конструкция case является многовариантным оператором и представляет собой частный случай условного оператора if. Эта конструкция часто используется при создании меню. Конструкция for представляет собой цикл, однократно обрабатывающий всю информацию для каждого значения, включенного в список, до тех пор, пока не встретится окончание списка.

Кроме сравнения значений или переменных, управляющие конструкции if и while можно применять для проверки того, успешно или неудачно была выполнена системная команда Linux. Напомним, что в Linux каждая выполняемая команда возвращает код завершения. Если выполнение команды было успешным, ее код завершения равен 0. Если по какой-либо причине команда не была выполнена успешно, кодом завершения будет некоторое положительное значение, указывающее тип ошибки. Управляющие кон­струкции if и while позволяют проверить, чему был равен код завершения: 0 или некоторому другому значению. Если код завершения равен нулю, значит, выполнение команды было успешным и управляющая конструкция if или while будет завершена.

Команда test . Сравнивать значения можно не только с помощью условных управляющих конструкций, но также с помощью команды test. При сравнении двух значений test возвращает 0 в том случае, если сравнение будет успешным. Команда test позволяет сравнивать целые числа, строки и даже выполнять логи­ческие операции. Совместно с командой test применяют опции, которые задают тип сравнения. Полный перечень опций приведен в таблице 2.

Таблица 2. Операции, выполняемые командой test интерпретатора BASH shell

Сравнение целых чисел

Функция

Больше чем

Меньше чем

Больше чем либо равно

Меньше чем либо равно

Не равно

Сравнение строк

Функция

Проверка на наличие пустой строки

Проверка на наличие строкового значения

Проверка строк на равенство

Прооверка строк на неравенство

Проверка на наличие строки, состоящей из нулей

Логические операции

Функция

Логическое И

Логическое ИЛИ

Логическое НЕ

Проверка файлов

Функция

Установка факта существования файла и его регулярности

Проверяется, не является ли файл пустым

Проверка возможности считывания из файла

Проверка возможности записи в файл, а также его изменения

Проверяется, является ли файл исполнимым

Проверяется, является ли имя файла именем каталога

Проверяется, является ли имя файла символической ссылкой

Проверяется, обозначает ли имя файла байт-ориентированное устройство

Проверяется, обозначает ли имя блок-ориентированное устройство

Команда test имеет следующий синтаксис:

test значение -опция значение

test строка = строка

В следующем примере покажем пример использования команды test. Сравним целочисленных значения, для этого используем опцию равенства –eq. Для проверки результата выполнения операции сравнения используем код завершения последней выполненной командыtest, который храниться в переменной $? интерпретатораshell.

$ tot = 4

$ test $ tot -eq 7

$ echo $?

1

Также команда test $tot –eq 7 может быть записана и в другом виде:

$ [ $tot –eq 7 ]

Условные конструкции: if, if-else, elif, case . Интерпретатор BASH shell включает несколько условных управляющих конструкций (табл. 3), которые позволяют выбирать для выполнения определенные команды Linux. Многие из этих конструкций напоминают условные управляющие конструкции в языках программирования, но имеются и некоторые отличия.

Таблица 3 – Управляющие конструкции интерпретаторов bash Shell

Условные управляющие конструкции

Функция

if команда then команда fi

Конструкция if вызывает выполнение действия в случае, если результат проверки истинен

if команда then команда else команда fi

Конструкция if-else вызывает выполнение действия в случае, если код завершения проверяемой команды paвен значению «истина», в противном случае выполняется действие else

if команда then команда elif команда then команда else команда fi

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

case строка in шаблон) команда;; еsас

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

команда && команда

Логическая операция И возвращает значение 0 («истина»), если обе команды возвращают значение 0; если же одна из команд возвращает ненулевое значение, резуль­тат операции И равен «ложь» и данная операция воз­вращает ненулевое значение

команда | | команда

Логическая операция ИЛИ, возвращающая значение 0 («истина») в случае, если одна или обе команды возвра­щают значение 0 («истина»); если обе команды возвра­щают ненулевое значение, то результат операции ИЛИ - «ложь» и операция возвращает ненулевое значение

Команда

Логическая операция НЕ, инвертирует код завершения команды

while команда do команды done

Конструкция while выполняет действие до тех пор, пока команда проверки возвращает значение «истина»

until команда do команды done

Конструкция until выполняет действие до тех пор, пока команда проверки возвращает значение «ложь»

Циклические управляющие конструкции

Функция while, until, for, for-in, select

for переменная in список-значений do команды done

Конструкция for-in предназначена для обработки списка значений. Переменной последовательно присваиваются значения из списка

for переменная do команды done

Конструкция for предназначена для последовательной обработки аргументов сценария. Переменной последовательно присваивается значение каждого аргумента

select строка in перечень-элементов do команды done

Конструкция select создает меню на основе элементов заданного списка, а затем выполняется указанная команда (обычно это команда case)

Условная конструкция if - then . Условная конструкция if ставит условие на выполнение команды. Этим условием является код завершения какой-то конкретной команды Linux. Если команда выполнена успешно (то есть код завершения равен 0), то команды внутри конструкции if выполняются. Если код завершения отличен от 0, то команды внутри конструкции if выполняться не будут. Иногда требуется выбрать один из двух вариантов, в зависимости от того как была выполнены команда Linux. Ключевое слово else конструкции if позволяет выбрать один из двух вариантов. Приведем синтаксис команды if-then-else.

Что такое shell и зачем он нужен

Командная оболочка в любых 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 позволяют автоматизировать многократно повторяющиеся действия. Имеется возможность объединять группы команд в логические блоки. Вы можете даже писать настоящие функции с передачей в них параметров. Таким образом, налицо все признаки и характеристики полноценного языка программирования. Попробуем извлечь из этого двойную пользу – наряду с изучением основ программирования автоматизируем свою повседневную работу.

Hello, World! Простая система резервного копирования

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

#!/bin/bash # # Резервное копирование каталогов и файлов из домашнего каталога # Этот командный скрипт можно автоматически запускать при помощи cron # cd $HOME if [ ! -d archives ] then mkdir archives fi cur_date=`date +%Y%m%d%H%M` if [ $# -eq 0 ] ; then tar czf archive${cur_date}.tar.gz projects bin else tar czf archive${cur_date}.tar.gz $* fi if [ $? = 0 ] ; then mv archive${cur_date}.tar.gz $HOME/archives echo "$cur_date – Резервное копирование успешно завершено." else echo "$cur_date – ОШИБКА во время резервного копирования." fi

Любой командный сценарий (script – скрипт, так называются программы командной оболочки) начинается со строки идентификатора, в которой явно задаётся интерпретатор команд с указанием полного пути к нему. Полный путь – последовательное перечисление всех каталогов, начиная с корневого, в которые надо войти, чтобы добраться до целевого файла, и, разумеется, имя этого файла. Запись полного пути чрезвычайно важна для однозначной идентификации каждого файла в иерархии файловой системы.

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

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

Наконец-то мы добрались до первой «настоящей» команды. Она позволяет сменить каталог (Change Directory), т.е. перейти из текущего каталога в другой, переданный команде как аргумент. В большинстве случаев целевой каталог задаётся в явной форме, например, cd /tmp или cd projects, но в нашем случае используется предопределённая системная переменная HOME – в ней содержится полный путь к домашнему каталогу текущего пользователя, от имени которого выполняется командный сценарий. Тем самым мы избавляемся от необходимости вносить изменения в код всякий раз при смене пользователя, потому что команда возвращает любого в его личный каталог. Знак доллара "$" перед именем переменной означает, что необходимо извлечь значение, содержащееся в этой переменной, и подставить его в командную строку вместо её имени. Особо следует отметить, что в командном языке оболочки регистров букв имеют важное значение, т.е. HOME, Home и home – это три различные переменные. По соглашению, буквами верхнего регистра обозначаются имена системных переменных: HOME, PATH, EDITOR и т.д. Это соглашение не запрещает пользователям создавать свои переменные с именами из заглавных букв, но зачем усложнять себе жизнь, нарушая общепринятые нормы и правила? Не рекомендуется также изменять значения системных переменных без крайней необходимости. В общем, соблюдаем простое правило: системные переменные используем только для чтения, а если потребовалась собственная, то её имя записываем буквами нижнего регистра.

Нашу первую команду можно было бы записать более кратко:

cd ~

Здесь символ "~" также означает домашний каталог текущего пользователя. Ветераны командной строки выражаются ещё лаконичнее:

cd

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

На очереди классическая программная конструкция проверки условия и принятия соответствующего решения. Общая схема такова:

if <условие> then <одна или несколько команд> fi

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

Для проверки условия, как правило, применяется команда test или её альтернативная форма записи в квадратных скобках. Иначе говоря, записи

if [ ! -d archives ] if test ! -d archives

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

Критерии проверки условия определяются разнообразными флагами. Команда test распознаёт очень большой их список. В нашем примере использован флаг -d, позволяющий проверить, соответствует ли заданное после флага имя реально существующему каталогу (directory). Наиболее часто при работе с файлами применяются следующие флаги:

F – существует ли обычный файл с заданным именем;

R – установлено ли для заданного файла право на чтение из него;

W – установлено ли для заданного файла право на запись в него;

X – установлено ли для заданного файла право на его выполнение;

S – имеет ли заданный файл ненулевой размер.

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

if [ ! -d archives ] Если не существует каталог archives (в текущем каталоге), then то начать выполнение блока команд: mkdir archives создать каталог archives (в текущем каталоге) fi завершить выполнение блока команд.

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

В следующей строке мы создаём собственную локальную переменную cur_date. В подавляющем большинстве случаев переменные создаются простым присваиванием конкретного значения, например:

ten=10 string="Это строка текста"

Но в нашем примере применяется небольшая хитрость. Обратите внимание, что после знака равенства – символа присваивания – записана команда в обратных кавычках. Такая форма записи позволяет присвоить переменной не саму строку, а результат её выполнения. Здесь это вывод команды date, которая возвращает текущую дату и время в формате, определяемом списком параметров:

%Y – текущий год в полной форме, т.е. из четырёх цифр (например, 2009);

%m – номер текущего месяца (например, 09 – для сентября);

%d – номер текущего дня;

%H – текущий час в 24-часовом формате;

%M – текущая минута.

Таким образом, если выполнить команду

cur_date=`date +%Y%m%d%H%M`

десятого сентября 2009 года в 22:45, то переменной cur_date будет присвоено строковое значение "200909102245". Цель этого ухищрения – сформировать уникальное, не повторяющееся имя архивного файла. Если вы намерены запустить несколько экземпляров программы в течение одной минуты, то можете улучшить уникальность имён, добавляя ещё и текущие секунды. Как? Изучите руководство утилиты date (man date) – в этом нет ничего сложного.

Прежде чем приступить к созданию файла архива, необходимо определить, какие именно каталоги мы будем сохранять в нём. Для большей гибкости можно задать набор каталогов, архивируемых по умолчанию, но предусмотреть возможность замены этого набора списком каталогов, передаваемым как аргумент в наш командный сценарий. Для этого используются специальные переменные командной оболочки: $# – число переданных в сценарий параметров и $* – все переданные параметры, записанные в формате одной строки.

if [ $# -eq 0 ] ; then

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

tar czf archive${cur_date}.tar.gz projects bin

Команда создания архивного файла и сжатия этого файла. Сама утилита tar не выполняет сжатие, а только лишь собирает все заданные файлы и каталоги в единый tar-файл. Для этого предназначен первый флаг - c (create – создать). Сжатие выполняет внешняя программа – здесь это gzip, вызываемый вторым флагом - z. Если в вашей системе установлена более эффективная программа сжатия bzip2, то вы можете воспользоваться ею, изменив команду следующим образом:

tar cjf archive${cur_date}.tar.bz2 projects bin

Третий флаг f сообщает о том, что далее следует имя архивного файла, поэтому всегда является замыкающим в перечне флагов. Обратите внимание на то, что при подстановке имя переменной заключено в фигурные скобки. Это сделано, чтобы явно выделить переменную в окружающей её строке, тем самым устраняя многие потенциальные проблемы. Расширения архивному файлу не присваиваются автоматически, вы сами дописываете всё необходимое. В качестве каталогов, архивируемых по умолчанию, я указал projects и bin, но вы можете записать здесь имена своих наиболее ценных каталогов.

Ключевое слово else открывает альтернативную ветвь выполнения. Команды этого блока начинают работать, если проверка условия даёт результат «ложь» (в нашем примере: «число переданных параметров ненулевое», т.е. пользователь задал имена каталогов). В этом случае команда будет выглядеть так:

tar czf archive${cur_date}.tar.gz $*

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

В конце программы выполняется ещё одна проверка. В unix-средах все команды возвращают код статуса завершения своей работы. Если команда отработала успешно, то она возвращает код 0, в противном случае код завершения будет ненулевым. Чтобы проверить успешность выполнения предыдущей команды архивации, воспользуемся ещё одной специальной переменной $?, в которой всегда содержится значение кода завершения самой последней команды. Если в переменной $? содержится 0, т.е. файл резервной копии был успешно создан, то мы перемещаем его в каталог архивов:

mv archive${cur_date}.tar.gz $HOME/archives

и выдаём соответствующее сообщение:

echo "$cur_date – Резервное копирование успешно завершено."

Если проверка показала, что код завершения операции архивирования не равен нулю, то выводится сообщение об ошибке:

echo "$cur_date – ОШИБКА во время резервного копирования."

На этом работа нашего командного сценария завершается.

Чтобы проверить работу нашей программы, необходимо сохранить описанный выше исходный код в файле, например, с именем bckp, а затем для удобства сделать его выполняемым:

chmod 750 bckp

и запустить:

./bckp

для создания резервной копии каталогов, заданных по умолчанию, и

./bckp docs progs works

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

Можно поместить файл bckp в один из каталогов, указанных в системной переменной PATH. Наиболее предпочтительными местами размещения являются /usr/local/bin или $HOME/bin, если таковые у вас имеются. После этого вы можете запускать bckp как системную команду.

Как автоматизировать операции резервного копирования «по расписанию»

Несколько слов об автоматизации резервного копирования. Для этой цели служит системный планировщик cron, который считывает рабочие инструкции из специального crontab-файла. Чтобы определить такие инструкции, необходимо создать и отредактировать свой crontab-файл при помощи команды:

crontab -e

Инструкции записываются в строго определённом формате (поля разделяются пробелами):

минуты часы день_месяца месяц день_недели команда

Один из вариантов расписания операций резервного копирования может выглядеть следующим образом:

30 23 10,20,30 * * /usr/local/bin/bckp

Это означает, что сценарий резервного копирования (следует указать полный путь к этому файлу) будет выполняться в 23:30 10-го, 20-го и 30-го числа каждого месяца независимо от дня недели. (Звёздочки обозначают весь допустимый диапазон значений, в данном случае: каждый месяц – в 4-м поле, любой день недели – в 5-м поле)

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

0 5 * * 3,5 /usr/local/bin/bckp

Здесь резервные копии будут создаваться в 5:00 по средам и пятницам в каждом месяце (звёздочка в 4-м поле), независимо от числа (звёздочка в 3-м поле).

Обо всех тонкостях составления расписания можно прочитать в руководстве man 5 crontab.

Итоги и выводы

Рассмотренный в данной статье сценарий резервного копирования обладает скромными функциональными свойствами. Но не в этом состояла его главная задача, а в том, чтобы читатель понял, что можно делать в командной строке, и не только скопировал и выполнил предложенный командный файл, а заинтересовался расширением его функций, занялся исследованием необъятных возможностей, предоставляемых командными оболочками. И если кто-то, прочитав эту статью, попробует усовершенствовать приведённый здесь код, или напишет собственный вариант, или реализует свою независимую идею, то я сочту, что основная цель достигнута.

Ресурсы для скачивания

static.content.url=http://www.сайт/developerworks/js/artrating/

ArticleID=458335

ArticleTitle=Основы программирования в командной оболочке shell