Введение в POSIX'ивизм

       

Сценарии оболочки: первые представления


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

А в заключение этого раздела - еще немного терпения. Потому что было бы несправедливо не уделить чуть-чуть места тому, что придает командному интерфейсу POSIX-систем его несравненную гибкость и универсальность. Заодно способствуя закоснению пользователя в смертном грехе лености. Итак - слово о сценариях оболочки.

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

Только не заподозрите меня в гнусном намерении учить вас программерству. Господь борони, и в мыслях не держал (тем паче, что и сам-то этим ремеслом не владею в должной для обучения других степени). Нет, просто на протяжении последующих глав нам то и дело придется рассматривать кое-какие примеры готовых сценариев, а подчас и пытаться создавать их собственноручно. Ибо занятие это в элементарном исполнении навыков программирования не требует вообще.

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

Сценарии в Unix-системах несколько напоминают batch-файлы, памятные многим по временам MS DOS, или макросы, знакомые пользователям любых развитых прикладных пакетов. Подобно тем и другим, они предназначены в первую очередь для автоматизации часто исполняемых рутинных операций. В частности, именно они позволяют избежать ввода длинных последовательностей в командной строке.

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

Создание пользовательского сценария - просто, как правда. Для этого всего и нужно:

  • создать командную конструкцию, достойную увековечивания;


  • поместить ее в простой текстовый файл;


  • по потребности и желанию снабдить комментариями;




  • тем или иным способом запустить файл на исполнение.


  • С принципами создания команд и командных конструкций мы в первом приближении разобрались (или пытались разобраться) раньше. А вот способов помещения их в файл существует множество. Можно просто ввести (или вызвать из буфера истории) нужную команду и оформить ее как аргумент команды echo, вывод которой перенаправить в файл:

    $ echo "cp -rf workdir backupdir" > mybackup

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

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

    $ cat > myarchive

    и нажимаем Enter. После этого команда остается в ожидании ввода данных для помещения их в новообразованный файл. Не обманем ее ожиданий и проделаем это. Причем можно не жаться и выполнить ввод в несколько строк, например:

    cd $HOME/archivedir tar cf archive.tar \ ../workdir gzip archive.tar



    Завершив ввод тела скрипта, все той же клавишей Enter открываем новую строку и набираем комбинацию Control+D, выдающую символ окончания файла.

    В результате получаем сценарий для архивирования в специально предназначенном для этого каталоге archivedir наших рабочих данных (командой tar), а заодно и их компрессии (командой gzip) - в Unix, в отличие от DOS/Windows, архивирование и компрессия обычно рассматриваются как разные процедуры).

    Наконец, сценарий можно создать в любом текстовом редакторе. но это не так интересно (по крайней мере, пока). Да и стоит ли вызывать редактор ради двух-трех строк?

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

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

    #!/path/shell_name

    В данном случае восклицательный знак подчеркивает, что предваряющий его символ решетки (#) - не комментарий, а указание (т.н. sha-bang) на точный абсолютный путь к исполняемому файлу оболочки, для которой наш сценарий предназначен, например,

    #!/bin/sh

    для POSIX-шелла, или

    #!/bin/bash

    для оболочки bash. Здесь следует подчеркнуть, что шелл, для которого предназначается сценарий, отнюдь не обязан совпадать с командной оболочкой пользователя. И полноты картины для замечу, что указание точного имени интерпретатора требуется не только для шелл-скриптов, но и для программ на любых языках сценариев (типа Perl или Python).

    Так что по хорошему в обоих приведенных выше примерах ввод команд сценария следовало бы предварить строкой sha-bang. Конечно, отсутствие имени командной оболочки в явном виде обычно не помешает исполнению шелл-сценария - для этого будет вызван командный интерпретатор по умолчанию, то есть /bin/sh во FreeBSD или /bin/bash в Linux (файл /bin/sh, который обязан присутствовать в любой POSIX-системе, в Linux представляет собой символическую ссылку на /bin/bash и предназначен для имитации POSIX-шелла).



    Однако если сценарий предназначен для другой командной оболочки, то без sha-bang он может исполняться неправильно (а если оболочка еще и не из семейства совместимых с POSIX shell - то не исполняться вообще).

    К слову сказать, если вписать строку sha-bang лениво - то следует еще и воздержаться от комментария в первой строке: в некоторых случаях он может быть интерпретирован как вызов конкретной оболочки (в частности, csh или tcsh). Лучше оставить первую строку свободной или начать сценарий с "пустой" команды :, не совершающей никакого действия.

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

    $ bash scriptname

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

    $ . ./scriptname

    с тем только исключением, что тут требуется указание текущего каталога в явном виде (что и символизируется ./).

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

    Так вот, после присвоения нашему сценарию бита исполнения запустить его можно точно также, как любую другую команду - просто из командной строки:

    $ ./scriptname

    Опять же - в предположении, что сценарий находится в текущем каталоге (./), иначе потребуется указание полного пути к нему. Что, понятно, лениво, но решается раз и навсегда: все сценарии помещаются в специально отведенный для этого каталог (например, $HOME/bin), который и добавляется в качестве еще одного значения переменной PATH данного пользователя.


    Содержание раздела