Россия, Москва |
Введение в программирование CGI-скриптов и программирование скриптов на bash
Переменные окружения
Переменные окружения (оболочки) создаются в момент старта bash -скрипта. При этом существует два типа переменных — те, которые действуют только в данной оболочке, и те, которые наследуются извне. Для просмотра переменных окружения можно использовать команду set:
bash-2.01$ set bash=/bin/bash bash_versinfo=([0]="2" [1]="01" [2]="0" [3]="1" [4]="release" [5]="i386-pc-freebsd2.2.2") bash_version='2.01.0(1)-release' columns=106 dirstack=() euid=1010 ...
Здесь не приводится полный список всех переменных окружения. Показано только, как этот список отображается. Каждая переменная передается парой "имя=значение". При этом каждая такая пара записывается с новой строки. Попробуем распечатать все переменные окружения скрипта в виде HTML-таблицы, используя bash:
#!/usr/freeware/bin/bash echo Content-type: text/html echo echo '<HTML><HEAD></HEAD><BODY>' echo '<H1>переменные окружения</H1>' echo '<TABLE BORDER=1>' echo '<TR><TD>Имя</TD><TD>значение</TD></TR>' IFS='=' set | while read x y do echo '<TR><TD>'$x'</TD><TD>'$y'</TD></TR>' done echo '</TABLE>' echo '<HR>' echo '</BODY></HTML>'
Первой командой echo формируется предложение HTTP-заголовка. Вторая команда echo обеспечивает пропуск строки между заголовком HTTP-сообщения и его телом. Затем начинает формироваться тело HTML-документа. Обратите внимание на прямые одинарные кавычки " ' ". Они применяются для того, чтобы защитить от интерпретации угловые скобки " < " и " > ", которые используются в bash для перенаправления стандартных потоков ввода/вывода.
Далее присваивается значение переменной окружения bash, которая не генерируется сервером HTTP — IFS. Переменная IFS хранит список символов-разделителей слов. По умолчанию это пробел и табуляция. Но нам нужно разделить имя переменной и его значения, которые на самом деле разделены символом "=".
Теперь вызываем команду set. При этом ее стандартный поток вывода перенаправляем при помощи "|" команде read, которая считывает строку из стандартного ввода, при этом присваивая переменным x и y значения последовательно от начала строки выделенных слов. А слова мы разделяем символом "=".
Читаем стандартный ввод в цикле while условие do.... done. В качестве условия все та же команда read — если считываем данные, то "истина", если нет, то — "ложь". При этом внутри цикла выводим строки таблицы "имя — значение".
B конце скрипта приводим документ к стандартному виду HTML-документа.
Обратиться к значению переменной окружения можно, конечно, гораздо проще — по имени:
#!/usr/freeware/bin/bash echo Content-type: text/html echo echo '<HTML><HEAD></HEAD><BODY>' echo '<H1>QUERY_STRING</H1>' echo QUERY_STRING = $QUERY_STRING echo '<HR>' echo '</BODY></HTML>'
Здесь по команде echo будет просто распечатано значение переменной окружения QUERY_STRING.
Аргументы командной строки
Позиционные параметры или аргументы командной строки — это последовательность строковых констант, которые указываются в командной строке после имени скрипта. Любая встроенная в bash команда или команда Unix может запускаться с набором этих параметров. Например, для того, чтобы подсчитать число активных в данный момент процессов httpd, администратор систем выдает такую последовательность команд:
bash>ps -ax | grep httpd | wc -l
Здесь указано три команды, организованные в конвейер. Каждая из них имеет по одному аргументу командной строки:
- ps задана с аргументом -ax ;
- grep задана с аргументом httpd ;
- wc задана с аргументом -l.
Позиционные параметры (аргументы командной строки) задаются встроенными переменными $1 — $n, где n — число аргументов. Аргументы командной строки появляются при запросах типа ISINDEX. Число аргументов командной строки определяется встроенной переменной bash — $#. Если мы вызовем скрипт по ссылке типа:
http://www.intuit.ru/cgi-bin/ argv.cgi?arg1+arg2+arg3,
то переменная $# примет значение 3, а переменные: $1 — arg1, $2 — arg2, $3 — arg3. Кстати, $0 — это имя самого скрипта. Распечатка параметров в виде HTML-таблицы может выглядеть следующим образом:
#!/usr/freeware/bin/bash echo Content-type: text/html echo echo '<HTML><HEAD></HEAD><BODY>' echo '<H1>Аргументы</H1>' echo '<TABLE BORDER=1>' echo '<TR><TH>Номер</TH><TH>Значение</TH></TR>' let i=0 for x in $@ do let i=i+1 echo '<TR><TD>arg['$i']</TD><TD>'$x'</TD></TR>' done echo '</TABLE>' echo '</BODY></HTML>'
Последовательность команд echo формирует HTTP-сообщение. Команда let позволяет выполнять арифметические вычисления. Перед циклом for производим инициализацию переменной i. Цикл for "пробегает" по всем аргументам командной строки, которые объединены в переменной $@ и разделяются в ней пробелами. Фактически они представляют собой список слов, по которому и бежит переменная цикла x. Обратите внимание на отличие данного цикла от стандартного цикла for в С или Perl: в нем не используются арифметические операции, а идет работа со списком.
Внутри цикла при помощи команды let мы увеличиваем индекс аргумента командной строки (значение переменной i ) и распечатываем этот индекс и значение переменной x в виде элементов HTML-таблицы.
Если аргументов мало и их местоположение известно, то к каждому из них можно просто обращаться по встроенному имени, например, первый аргумент — это $1.
Стандартный поток ввода
По большому счету, для чтения данных из стандартного потока ввода в рамках программирования CGI-скриптов bash непригоден. Дело в том, что в нем нет механизма посимвольного считывания данных. Bash -скрипт способен читать только строками и останавливает считывание лишь в случае появления в потоке символа конца файла. Как известно, HTTP-сервер такого символа в стандартный поток ввода скрипта при работе по методу POST не передает. Тем не менее чтение стандартного ввода в рамках программирования CGI-скриптов на bash применяется.
Примером тому может служить генерация гипертекстовых ссылок на файлы текущего каталога:
#!/usr/freeware/bin/bash echo Content-type: text/html echo echo '<HTML><HEAD></HEAD><BODY>' echo '<Ul>' ls -a | while read x do if test -f $x; then echo '<LI><A HREF=./'$x'>'$x'</A>'; fi done echo '</BODY></HTML>'
В данном случае команда ls доставляет в скрипт имена файлов. Один файл — это отдельная строка. Эти имена обрамляются гипертекстовыми ссылками и вставляются в HTML-страницу. При этом печатаются только обычные файлы, все остальные игнорируются.
Другой пример — фильтрация. При приеме по методу GET запрос размещается в переменной QUERY_STRING. Но он там находится в форме form-urlencoded. Для его фильтрации вызывается внешняя программа, стандартный вывод которой перенаправляется на стандартный ввод одной из команд скрипта:
echo $QUERY_STRING | tr '+' ' ' | while read x do for y in $x do echo $y done done
Существуют и другие способы применения чтения из стандартного ввода при программировании CGI-скриптов на BASH.