CGI

CGI (Common Gateway Interface — «общий интерфейс шлюза») — стандарт интерфейса(см. RFC 3875: CGI Version 1.1), используемого для связи внешней программы с веб-сервером. Программу, которая работает по такому интерфейсу совместно с веб-сервером, принято называть шлюзом, или скрипт (сценарий) или «CGI-программа».

Гипертекст в "первозданном" виде монументален по своей природе, веб-страница не может непосредственно взаимодействовать с пользователем, подобная Web страница пример статической страницы, естественно это устраивало до поры до времени, до момента появления необходимости интерактивного общения, что стало примером динамической страницей, динамические страницы это интерактивные страницы, страницы которые могут создавать отчеты на основе предоставляемых пользователем сведений , по мимо этого они применяются для отображения изменяющейся информации в режиме реального времени, либо для осуществления задачи мониторинга, до появления JavaScript, не было иной возможности отреагировать на действия пользователя, кроме как передать введенные им данные на веб-сервер для дальнейшей обработки. В случае CGI эта обработка осуществляется с помощью внешних программ и скриптов, обращение к которым выполняется через стандартизованный интерфейс — общий шлюз. Сам интерфейс разработан таким образом, чтобы можно было использовать любой язык программирования, который может работать со стандартными устройствами ввода-вывода, поэтому в простых случаях могут использоваться так же и скрипты командных интерпретаторов.

Как работает CGI?

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

    • Клиент запрашивает CGI-приложение по его URI.

    • Веб-сервер принимает запрос и устанавливает переменные окружения, через них приложению передаются данные и служебная информация.

    • Веб-сервер перенаправляет запросы через стандартный поток ввода (stdin) на вход вызываемой программы.

    • CGI-приложение выполняет все необходимые операции и формирует результаты в виде HTML.

    • Сформированный гипертекст возвращается веб-серверу через стандартный поток вывода (stdout). Сообщения об ошибках передаются через stderr.

    • Веб-сервер передает результаты запроса клиенту.

Области применения CGI

Наиболее частая задача, для решения которой применяется CGI — создание интерактивных страниц, содержание которых зависит от действий пользователя. Типичными примерами таких веб-страниц являются форма регистрации на сайте или форма для отправки комментария. Другая область применения CGI, остающаяся за кулисами взаимодействия с пользователем, связана со сбором и обработкой информации о клиенте:

    • установка и чтение cookies;

    • получение данных о браузере и операционной системе;

    • подсчет количества посещений веб-страницы; мониторинг веб-трафика и т.п.

Эти возможности обеспечиваются тем, что CGI-скрипт может быть подключен к базе данных или обращаться к файловой системе сервера. Таким образом CGI-скрипт может сохранять информацию в таблицах БД или файлах и получать ее оттуда по запросу, чего нельзя сделать средствами HTML. CGI — это не язык программирования! Это "простой" протокол, позволяющий веб-серверу передавать данные через stdin и читать их из stdout. Поэтому, в качестве CGI-обработчика может использоваться любая серверная программа, способная работать со стандартными потоками ввода-вывода. Аббревиатура CGI обозначает спецификацию, которая задает для получающих информацию сценариев способ обмена данными с сервером. Такие CGI - сценарии могут быть созданы с помощью любого(что важно) языка написания сценариев, наиболее популярным является Perl, хотя с этой целью можно применять и обычные shell - сценарии.

Недостатки

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

Не смотря на это CGI и на сегодняшний день один из распространенных способов создания динамических Web-страниц.

Неофициальное исследование эффективности CGI и серверного JavaScript

*** В то время как CGI-программы взаимодействуют с сервером через STDIN и STDOUT запущенного CGI-процесса, FastCGI-процессы используют Unix Domain Sockets или TCP/IP для связи с сервером. Это даёт следующее преимущество над обычными CGI-программами: FastCGI-программы могут быть запущены не только на этом же сервере, но и где угодно в сети. Также возможна обработка запросов несколькими FastCGI-процессами, работающими параллельно. Как и CGI, FastCGI не является языком, можно сказать что это CGI с несколькими расширениями, как и CGI, FastCGI также не зависит от языка и использует тот же RFC 3875 . https://ru.wikipedia.org/FastCGI

Схема работы

    1. Браузер заполняет форму и клики. Формализованная информация отправляется на веб-сервер.

    2. Веб-сервер обрабатывает ("grabs") информацию из формы и передает ее в CGI.

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

    4. Затем CGI выполняет подготовленный запрос данных, который передается к драйверу базы данных.

    5. Драйвер базы данных действует как посредник и выполняет запрошенное действие в базе данных.

    6. Результаты действия базы данных затем передаются обратно драйверу базы данных.

    7. Драйвер базы данных отправляет информацию из базы данных в программное обеспечение CGI.

    8. Программное обеспечение CGI берет информацию из базы данных и конвертирует ею в необходимый формат.

    9. Если необходимо создать статические HTML-страницы, программа CGI обратится к серверной файловой системе, а также к read/writes &/or.

    10. Затем программное обеспечение CGI отправляет сформированный результат обратно на веб-сервер.

    11. Веб-сервер отправляет результат, полученный от программного обеспечения CGI, обратно в браузера пользователя.

Когда броузер генерирует запрос на загрузку страницы, Web–сервер задается в виде входящего URL. Если в качестве части URL–пути указывается cgi-bin, сервер открывает соединение, которое обычно реализует перенаправление к запрашиваемому cgi-сценарию. Входной и выходной поток сценария cgi отсылаются с помощью этого перенаправления. Если сценарий cgi используется для отображения форматированной Web–страницы, он должен включать теги HTML.

Тестовый сценарий cgi

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

Все сценарии обычно находятся в каталоге /usr/lib/cgi-bin/ Web–сервера(Debian), хотя подобное размещение может быть изменено. Для изменения размещения сценариев и подключения сервера cgi следует обратиться к файлам конфигурации apache2.conf (/etc/apache2) и разделу ScriptAlias, которого нет и необходимо его создать, очень полезно поинтересоваться содержимым модуля cgi, который необходимо активировать: sudo a2enmod cgi . Все сценарии должны иметь расширение .cgi. Все документы обычно размещаются в каталоге html либо htdocs и имеют расширение .html. Для всех сценариев требуется установить следующие права доступа: chmod 755 script.cgi

По умолчанию любые подключения к Web–странице обычно осуществляются от имени пользователя nobody, хотя это можно изменить с помощью файла конфигурации httpd.conf(apache2.conf), неплохо было бы проверить, отключено ли поле пароля "nobody". Если это так, запрещается подключение для произвольных пользователей, в то время как пользователь nobody физически подключен к терминалу. Для отключения пароля пользователя nobody в соответствующее поле пароля просто вставьте звездочку (файл пароля /etc/passwd). Если какой-либо из сценариев не функционирует, первым делом нужно просмотреть журнальные файлы ошибок(например /var/log/apache2, тот который указан в конфиге сайта). В этих файлах содержатся четкие описания всех возникших ошибок. Сценарии могут быть также протестированы путем выполнения их запуска из командной строки. Конечно, в этом случае вы получите только текстовый вывод, но он окажет вам помощь при дальнейшей отладке.

Приступая к созданию сценария cgi введем указанный ниже текст в файл, назовем его firstpage.cgi и сохраним в каталоге /usr/lib/cgi-bin/. He забывая установить для сценария права доступа: chmod 755 firstpage.cgi и активировать модуль:

$ sudo a2enmod cgi, в /etc/apache2/apache2.conf добавить строчку: ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ (и это не единственный, но стандартно надежный вариант)

$ ~ cat > firstpage.cgi

#!/bin/sh

#firstpage.cgi

#отображение тестовой страницы

echo "Content-type: text/html"

echo ""

echo "<HTML>"

echo "<H1><CENTER> THIS IS MY FIRST CGI PAGE</CENTER></H1>"

echo "<HR>"

echo "<H2><CENTER>You are to stand a good chance! </CENTER></H2>"

echo "<H3><CENTER>httpd.conf (Debian: /etc/apache2/apache2.conf):

ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ >>>> http://WebServer/cgi-bin/firstpage.cgi</CENTER></H3>"

echo "<H2><CENTER>cmod 755 firstpage.cgi; sudo a2enmod cgi; sudo service apache2 reload</CENTER></H2>"

echo "</HTML>"

^C

$ ~

$ ~ cmod 755 firstpage.cgi

Первая строка, содержащая команду echo, сообщает серверу о том, что это заголовок MIME; вторая команда echo сообщает о новой строке. Вывод сценариев cgi не будет осуществляться, если не указана новая строка после заголовка MIME (MIME определяет механизмы для передачи разного рода информации внутри текстовых данных).

Если вы забудете указать какие-либо закрывающие теги, не беспокойтесь — вы их вскоре обнаружите, поскольку при попытке загрузки в окно броузера подобного документа открывающие теги, для которых отсутствуют закрывающие, будут отображены на экране. Теперь для отображения документа введите URL: http://ваш_cepвep/cgi-bin/firstpage.cgi

https://code.tutsplus.com/articles/apache-aliasing-and-redirection

http://ashep.org/2013/apache-aliasing-i-redirekt

http://dedicatesupport.com/content/nastroika-cgi-skriptov-v-apache-2

https://www.linux.org.ru/forum/admin/11152079

https://drive.google.com/file/sharing <<----Perl PDF

https://drive.google.com/file/sharing <<----Perl Матросов, Чаунин "Самоучитель"

https://drive.google.com/file/sharing <<----HTML PDF

https://drive.google.com/file/sharing <<----CGI Основы PDF


Отображение вывода команды интерпретатора shell

Поместим команду интерпретатора shell в сценарий, при этом вывод команды будет отображен в документе HTML. Вы можете увидеть, сколько пользователей зарегистрировано на данный момент времени. Выполните команду who и отфильтруйте ее выводе помощью команды wc (USERS=`who |wc -l`). В результате отобразится количество зарегистрированных пользователей. Также выводится значение даты. Соответствующий сценарий имеет вид:

$ sudo cat > pagetwo.cgi

#!/bin/sh

#pagetwo.cgi

#отображение страницы с помощью вывода команды Unix

MYDATE=`date +%A" "%d" "%B" "%Y`

USERS=`who |wc -l`

echo "Content-type: text/html"

echo ""

echo "<HTML>"

echo "<H1><CENTER> THIS IS MY SECOND CGI PAGE</CENTER></H1>"

echo "<HR>"

echo "<H2><CENTER>$MYDATE</CENTER></H2>"

echo "<H3><CENTER> Total amount of users on to-day: $USERS</CENTER></H3>"

echo "<PRE>"

if [ "$USERS" -lt 10 ]; then

echo "<CENTER> It must be early or it ls dinner time</CENTER>"

echo "<CENTER> because there ain't many users logged on</CENTER>"

fi

echo "</PRE>"

echo "</HTML>"

^C

$ sudo chmod 755 pagetwo.cgi

$

В начале сценария считывается информация о дате и текущих пользователях. Дата отображается в центральной части страницы. Также отображается значение переменной $USERS. Конструкция if используется для определения, является ли число зарегистрированных пользователей меньшим десяти; если это условие выполняется, отображается сообщение "It must be early or it's dinner time".

Тег <PRE> применяется для сохранения опций форматирования, состоящих из служебных символов и символов табуляции. Обычно тег <PRE> используется для отображения вывода системных команд, таких как df, либо списка файлов, либо нескольких конструкций echo.

В данном случае вовсе не обязательно применять тег <PRE>, однако автор (Д.Тейнсли) специально упомянул этот тег на ранней стадии для того, чтобы пользователь уже сейчас сознательно использовал его для разработки собственных Web–страниц. Для отображения документа введите следующий адрес: http://ваш_cepвep/cgi-bin/pagetwo.cgi

SSI

http://citforum.ru/internet/html/ssi.shtml

https://httpd.apache.org/docs/current/howto/ssi.html <<-------Apache

https://nginx.ru/ru/docs/http/ngx_http_ssi_module.html <<--------NGINX

Естественно использование сценариев cgi, открывающих Web–страницы с целью отображения определенного количества сведений, не всегда является оптимальным, гораздо эффективней внедрить сценарий cgi в документ HTML таким образом, чтобы вывод сценария отображался на обычной странице.

Для внедрения сценариев cgi в документы можно воспользоваться технологией SSI (Server Side Includes — включения на стороне сервера). При отображении документа происходит замена команды SSI результатом выполнения данной команды или сценария. При этом также экспортируются дополнительные переменные среды, содержащие сведения об установленном сервере и командах.

Для активизации возможностей SSI, обеспечивающих просмотр сервером команд SSI внутри документов, следует раскоментировать соответствующие:

Addhandler server-passed.shtml

Addtype text/html shtml

В Debian Apache2(etc/apache2/apache2.conf) всего этого нет, поэтому;

$ sudo a2enmod include #активировать модуль

прописать:

<Directory /var/www/*>

Options +Includes

AddType text/html .shtml

AddOutputFilter INCLUDES .shtml

</Directory>

https://httpd.apache.org/docs/current/howto/ssi.html

Для перезапуска сервера введите команду service apace2 reload (kill -1), в результате чего сервер повторно считает конфигурационные файлы. Документы, для которых применяется SSI, используют расширение файла shtml вместо расширения html.

Счетчик количества посещений

Создадим документ, в котором отображается счетчик количества посещений. Можно также отображать дату последнего изменения страницы. Не забудьте поместить сценарий в каталог cgi-bin; вызовите его путем ввода hitcount.cgi.

$ cat > hitcount.cgi

#!/bin/sh

#hitcount.cgi

#счетчик попыток доступа к страницам для html <cgi>

#файл счетчика должен иметь атрибуты

counter=../cgi-bin/counter

chmod 666 $counter

echo "Content-Type: text/html"

echo ""

read access < $counter

access=`expr $access + 1`

echo $access

echo $access >$counter

^C

$ chmod 755 hitcount.cgi

Как видно из приведенного кода, сценарий считывает файл ../cgi-bin/counter, присваивает его переменной access, добавляет к нему единицу, затем записывает результат обратно в файл

/cgi-bin/counter.

Теперь создадим файл counter. Все, что требуется в данном случае, — поместить в этот файл начальный номер; в качестве начального номера будет использована единица. Итак, создайте файл counter, введите в него 1, затем сохраните файл и выйдите из него.

$ cat > counter

1

^C

$ chmod 666 counter

$ sudo mv counter /usr/lib/cgi-bin/

$ sudo mv hitcount.cgi /usr/lib/cgi-bin/

Поскольку этот файл будет использоваться любым пользователем, необходимо присвоить ему права владельца, группы и других пользователей: chmod 666 counter

Теперь осталось создать файл с расширением .shtml и поместить его в корневой каталог Web, где обычно находятся другие документы HTML. Файл также может находиться в каталоге htdocs или html.

$ cat > main.shtml

<! main.shtml>

<! строка комментария >

<HTML>

<H4> Last modified: <!--#echo var="LAST_MODIFIED" -->

</H4>

<HR>

<H1><CENTER> OPERATIONS CENTER </H1></CENTER>

<H2><CENTER>Stand by to Stand to!,this page has been visited <!--#exec cgi="/cgi-bin/hitcount.cgi" --> times.</CENTER>

<HR>

<CENTER>Today is: <!--#echo var="DATE_LOCAL" --></CENTER>

</Н2>

<HR>

</HTML>

^C

$

Последняя изменяемая переменная, также как и другие переменные, экспортируются с помощью SSI. Обратитесь к Web–узлу apache (www.apache.org) для получения полного описания всех дополнительных переменных, которые были экспортированы с помощью SSI.

Посмотрите на команду SSI:

This page has been visited <!--#exec cgi="/cgi-bin/hitcount.cgi" --> times

как и <!--#echo var="DATE_LOCAL" --> ; <!--#echo var="LAST_MODIFIED" -->

Общий формат команды: <!--# команда аргумент= "значение" -->

В нашем случае для запуска cgi–сценария hitcount применяются следующие значения параметров:

    • команда - exec,

    • аргумент - cgi,

    • "значение" - имя вызываемого сценария.

В рассматриваемом случае файл конфигурации был изменен таким образом, что данная страница будет отображаться по умолчанию вместо страницы index.html. Но остается также возможность вызова файла с помощью указания полного пути. Обычно файл, который открывается веб-сервером при обращении к каталогу, имеет имена: index.htm или index.html.

Когда посетитель запрашивает ссылку на каталог (например, http://htaccess.net.ru/doc/), и такой каталог существует, то веб-сервер отдает из данного каталога файл «index.htm». А при его отсутствии - либо содержимое каталога (если включена опция Indexes), либо ошибку 403 ( FORBIDDEN ) если опция отключена (запрещен просмотр директорий). Если веб-сайт построен на скриптах, то в качестве индексных часто могут использоваться файлы с другими расширениями - указать эти файлы можно с помощью директивы DirectoryIndex , прописав ее в /etc/apache2/apache2.conf, а изучив содержание модуля dir.conf, возможно прописывать ни чего и не понадобится.

Например:

DirectoryIndex index.html index.shtml index.pl index.cgi index.php

При том, что модуль dir , должен быть активирован.

Не забудьте закрыть и перезапустить Web–сервер, чтобы изменения возымели эффект.

Для вызова сценария введите URL: http: //<имя_сервера>/main.shtml или http://<имя_сервера> если это страница, заданная по умолчанию.

Ниже показан пример страницы, содержащей счетчик посещений; для просмотра приращения счетчика достаточно просто обновить страницу. Обратите внимание, каким образом отображается значение переменной last_modified. Конечно, можно каждый день сбрасывать значение счетчика. Для этого нужно воспользоваться записью одиночной команды cron, которая отправляет в файл число 1.

Вывод на печать текущих настроек Web–среды с помощью ссылки

При выполнении сценария cgi какое-то количество переменных среды становится незадействован-ным. Для просмотра значений большинства переменных используется команда env или set. На основе файла main.shtml который по средствам ссылки на Web-странице, отразит значения этих переменных мы и продемонстрируем вывод на печать текущих настроек Web–среды с помощью ссылки.

Для начала создадим сценарий "cgi", по средствам которого и будет выведены значения параметров среды, назовем его printenv.cgi, поскольку для просмотра переменных понадобится env или set, выберем env, добавив для наглядности системный календарь.

$ cat > printenv.cgi

#!/bin/sh

# printenv.cgi

# вывод на печать настроек Web–сервера с помощью команды env

echo "Content-type: text/html"

echo ""

echo "<HR>"

echo "<HTML><PRE>"

env

echo "</PRE></HTML>"

# печатание календаря

echo "<HR>"

echo "<HTML><PRE>"

cal

echo "</PRE></HTML>"

echo "<HR>"

^C

$ chmod 755 printenv.cgi

$ sudo mv printenv.cgi /usr/lib/cgi-bin/

Теперь отредактируем файл main.shtml вставив тег с помощью которого отражаются ссылки:

<А HREF = "/cgi-bin/printenv.cgi">ENVIRONMENT</A>

Структура такова, <А HREF - тег открывающий; </A> - тег закрывающий, далее в кавычках пишется адрес или назначение, далее текст отображаемой ссылки, и в итоге вот что получается с main.shtml:

$ vim main.shtml

<! main.shtml>

<! строка комментария >

<HTML>

<H4> Last modified: <!--#echo var="LAST_MODIFIED" -->

</H4>

<HR>

<H1><CENTER> OPERATIONS CENTER </H1></CENTER>

<H2><CENTER>Stand by to Stand to!,this page has been visited <!--#exec cgi="/cgi-bin/hitcount.cgi" --> times.</CENTER>

<HR>

<CENTER>Today is: <!--#echo var="DATE_LOCAL" --></CENTER>

<CENTER>To see your environment settings just click <A HREF="/cgi-bin/printenv.cgi" > ENVIRONMENT</A></CENTER>

</Н2>

<HR>

</HTML>

И в результате:

Знание Perl расширит и упростит использование CGI приложений и вот ниже пример вывода текущих настроек Web-среды, с помощью Perl:

$ cat > envv

#!/usr/bin/perl

print "Content-type: text/html\n\n";

print "<html>\n<body>\n<h1>Environment</h1>\n";

foreach (sort keys %ENV)

{

print "<b>$_</b>: $ENV{$_}<br>\n";

}

print "</body>\n</html>";

exit;

^C

$

GET/POST методы - основы

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

После того как пользователь выполнил ввод или выбрал некоторые данные в форме, он может сделать клик на кнопке send для передачи введенной информации приложению, в нашем случае cценарию cgi. Как только информация будет введена, начинается работа методов get и post.

GET

По умолчанию используется метод get. Это один из методов применяемых для выборки файлов из статических HTML–страниц.

Как только пользователь делает клик на кнопке submit, информация, которая была выбрана или выбирается пользователем, добавляется к URL сервера в виде закодированной строки. Затем эта закодированная строка присваивается переменной среды сервера, "query_string". Переменная "request_method" также используется для хранения метода формы.

Создание простой формы - создадим сценарий books.cgi:

$ cat > books.cgi

#!/bin/sh

# сценарий books.cgi

echo "Content-type: text/html"

echo ""

echo "<HTML>"

echo "<BODY>"

# вызов books_result.cgi, затем пользователь щелкает на кнопке отправки !

echo "<FORM action="/cgi-bin/books_result.cgi" METHOD=GET>"

echo "<H4> CGI FORM</H4>"

#текстовое поле, результаты ввода присвоены переменной с именем 'contact'

echo "Your Name: <INPUT NAME=contact SIZE=30><BR><BR>"

#раскрытие выбранного пункта меню, присвоенного переменной 'film'

echo "<SELECT NAME=film>"

echo "<OPTION> -- Pick a Film --"

echo "<OPTION>A Few Good Men"

echo "<OPTION>Die Hard"

echo "<OPTION>Red October"

echo "<OPTION>The Sound Of Music"

echo "<OPTION>Boys In Company C"

echo "<OPTION>Star Wars"

echo "<OPTION>Star Trek"

echo "</SELECT>"

# раскрытие выбранного пункта меню, присвоенного переменной 'actor'

echo "<SELECT NAME=actor>"

echo "<OPTION>-- Pick Your Favourite Actor --"

echo "<OPTION>Bruce Willis"

echo "<OPTION>Basil Rathbone"

echo "<OPTION>Demi Moore"

echo "<OPTION>Lauren Bacall"

echo "<OPTION>Sean Connery"

echo "</SELECT>"

echo "<BR><BR>"

# имена переменных флажков 'view_cine' и 'view_vid'

echo "Do you watch films at the..<BR>"

echo "<INPUT TYPE="Checkbox" NAME=view_cine> Cinema"

echo "<INPUT TYPE="Checkbox" NAME=view_vid> On video"

echo "<BR><BR>"

# результаты ввода, присвоенного переменной 'textarea'

echo "Tell what is your best film, or just enter some comments<BR>"

echo "<TEXTAREA COLS="30" ROWS="4" NAME="textarea"></TEXTAREA>"

echo "<BR><INPUT TYPE=Submit VALUE="Send">"

echo "<INPUT TYPE="reset" VALUE="Clear">"

echo "</FORM>"

echo "</BODY>"

echo "</HTML>"

^C

$ chmod 755 books.cgi

$ sudo mv books.cgi /usr/lib/cgi-bin/

$

Действие form action выбирается, как только пользователь щелкнет на кнопке 'Send it', в результате чего вызывается сценарий books_result.cgi(который создадим ниже). В этом случае будет использоваться метод get.

В форме, код которой приведен выше, отображаются:

    • два текстовых поля

    • два раскрывающихся поля

    • два флажка ("Checkbox")

Текстовое поле, предназначенное для ввода пользовательского имени, имеет длину 30 символов; результаты ввода присваиваются переменной contact.

Первое раскрывающееся меню обеспечивает выбор любимого пользовательского фильма; выбранная опция присваивается переменной film.

Второе раскрывающееся меню обеспечивает выбор любимого актера; выбранная опция присваивается переменной actor.

Можно установить один или оба флажка ("Checkbox"), выполнив щелчок мышью на требуемом варианте. Выбранные значения хранятся в переменных "view_cine" и "view_vid".

Если пользователь указывает один из флажков, переменные должны иметь значение "on".

Область текстового поля обеспечивает ввод большего количества строк текста, чем стандартное текстовое поле (текст, разбитый на 30 столбцов и 4 строки, в нашем случае), а вся введенная информация присваивается переменной textarea.

Для отсылки данных в качестве типа ввода указывается слово "Send".

Чтобы очистить форму, щелкните на кнопке "Clear".

Создадим сценарий books_result.cgi и сохраним его в каталоге cgi-bin:

$ cat > books_result.cgi

#!/bin/sh

#сценарий books_result.cgi

#вывод на печать настроек web–сервера env для метода get

echo "Content-type: text/html"

echo ""

echo "<HTML><PRE>"

echo "<PRE>"

echo " Results from a GET form"

echo "REQUEST_METHOD : $REQUEST_METHOD"

echo "QUERY STRING : $QUERY_STRING"

echо "</PRE></HTML>"

^C

$ chmod 755 books_result.cgi

$ sudo mv books_result.cgi /usr/lib/cgi-bin/

$

Отредактируем файл main.shtml вставив следующие две строки после последней записи ссылки:

<BR> Basic form using GET method

<A HREF="/cgi-bin/books.cgi" >Form1</A>

$ sudo service apache2 restart

[ ok ] Restarting web server: apache2.

$

Сценарий отображает значения пары переменных cgi, "query_strinG" и "request_method". Переменная "query_string" будет хранить все данные в виде кодированной строки, которая отправлена формой, созданной с помощью сценария books.cgi. Переменная "request_method" сохраняет тип используемого метода; в данном случае будет выбран метод get.

Итого:

Форма cgi использующая метод get, выбор и ввод информации в форму ...и после Send:

Информация отправленная формой, закодирована

Декодирование закодированной строки

После того как пользователь щелкнет на кнопке "Send", информация присваивается переменной query_string, а строка кодируется следующим образом:

    • Все пробелы заменяются знаками +.

    • Все поля значений разделяются символами &.

    • Все значения и соответствующие поля разделяются знаками =.

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

Протокол cgi определяет, что любые символы в форме "%ху" (где xy является шестнадцатеричным числом) могут быть преобразованы в эквивалентные символы ASCII. Эти шестнадцатеричные символы состоят из специальных символов &, %, +, =, (, ) и всех других символов, выходящих за рамки десятичного диапазона ASCII с границей 127. Например, символу ( соответствует эквивалент в виде %29.

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

    • заменить все символы & символами перевода строки;

    • заменить все символы + пробелами;

    • заменить все символы = пробелами;

    • преобразовать все значения %xy в эквивалентные символы ASCII.

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

Следующий сценарий выполняет все необходимые преобразования, а также обеспечивает доступ к переменным.

$ cat > conv.cgi

#!/bin/sh

#сценарий conv.cgi

#декодирование строки URL

echo "Content-type: text/html"

echo ""

echo "<HTML><PRE>"

#отображение метода кодированной строки

echo "Method : $REQUEST_METHOD"

echo "Query String : $QUERY_STRING"

echo "<HR>"

#применение редактора sed для замены символов & символами табуляции

LINE=`echo $QUERY_STRING | sed 's/&/ /g'`

for LOOP in $LINE

do

#разбивка на поля NAME и TYPE, замена всех символов пробелами, a %hex_num -> \xhex_num,

#замена всех символов "+" пробелами

NAME=`echo $LOOP | sed 's/=/ /g' | awk '{print $1}'`

TYPE=`echo $LOOP | sed 's/=/ /g' | awk '{print $2}' | \

sed -e 's/%\(\)/\\\x/g' | sed 's/+/ /g'`

#используется функция printf, которая отображает значения переменных,

#после завершения преобразований шестнадцатеричных значений

printf "${NAME}=${TYPE}\n"

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

#передаются команде eval, благодаря чему отдельные поля можно адресовать,

#при этом если поля содержат пробелы, требуется удвоенная обратная косая черта

VARS=`printf "${NAME}=\\${TYPE}\n"`

eval `printf $VARS`

done

echo "<HR>"

#используется printf для отображения специальных символов в случае их наличия

printf "Your name is : $contact\n"

printf "Your choice of film is : $film\n"

printf "Your choice of actor is : $actor\n"

printf "You watch films at the cinema : $view_cine\n"

printf "You watch films on video : $view_vid\n"

printf "And here are your comments : $textarea\n"

echo "</PRE>"

echo "</HTML>"

^C

$ chmod 755 conv.cgi

$ sudo mv conv.cgi /usr/lib/cgi-bin/

$

Нетрудно заметить, что в данном случае используется функция printf для вывода данных на экран. Причина этому весьма проста. Функция printf выполняет те же действия, что и обычная команда echo, но дополнительно выполняет шестнадцатеричные преобразования. В связи с этим следует сделать небольшое замечание. При использовании функции printf не происходит вставка символа новой строки; для устранения этого недостатка необходимо после каждой функции printf указать символы "\n", Шестнадцатеричные числа, хранящиеся в переменной QUERY_STRING, имеют формат %hex_num. Этот формат будет просто преобразован в формат \xhex_num с помощью потокового редактора sed, а также функции printf, выполняющей все необходимые преобразования. Зачем создавать себе дополнительные трудности, если для решения задачи существует простой способ?

Сохранив указанный выше сценарий под именем conv.cgi в каталоге cgi-bin, отредактируем сценарии books.cgi, для того что бы форма вызывала сценарий conv.cgi, а не books_result.cgi, редактируем соответствующую строку: <FORM action = "/cgi-bin/conv.cgi" METHOD=GET>

Метод get является стандартным методом, применяемым для работы с формами. В зависимости от имеющегося окружения, при использовании метода get существуют две потенциальные проблемы. Вся закодированная строка добавляется к адресу URL при отсылке информации, поэтому отсылаемая информация может быть просмотрена в окнеURL, хотя многие пользователи не видят в этом особой опасности, все же не стоит посылать информацию частного характера с помощью Web или сети. (..и мало того, что пользователи не видят опасности, но ведь и многие "администраторы", то же ни чего не видят)

В итоге получим:

...и после Send:

POST

Отличие метода POST от GET заключается в способе получения данных: метод post считывает данные из стандартного потока. Для отсылки данных с помощью метода post необходимо заменить ключевое слово " METHOD=GET" словом " METHOD=POST" в конструкции FORM ACTION сценария, в нашем случае сценария books.cgi.

/usr/lib/cgi-bin$ vim books.cgi

#!/bin/sh

# сценарий books.cgi

echo "Content-type: text/html"

echo ""

echo "<HTML>"

echo "<BODY>"

# вызов books_result.cgi, затем пользователь щелкает на кнопке отправки !

#echo "<FORM action="/cgi-bin/conv.cgi" METHOD=GET>"

echo "<FORM action="/cgi-bin/conv.cgi" METHOD=POST>"

echo "<H4> CGI FORM </H4>"

#текстовое поле, результаты ввода присвоены переменной с именем 'contact'

echo "Your Name: <INPUT NAME=contact SIZE=30><BR><BR>"

#раскрытие выбранного пункта меню, присвоенного переменной 'film'

echo "<SELECT NAME=film>"

echo "<OPTION> -- Pick a Film --"

echo "<OPTION>A Few Good Men"

echo "<OPTION>Die Hard"

echo "<OPTION>Red October"

echo "<OPTION>The Sound Of Music"

echo "<OPTION>Boys In Company C"

echo "<OPTION>Star Wars"

echo "<OPTION>Star Trek"

echo "</SELECT>"

# раскрытие выбранного пункта меню, присвоенного переменной 'actor'

echo "<SELECT NAME=actor>"

echo "<OPTION>-- Pick Your Favourite Actor --"

echo "<OPTION>Bruce Willis"

echo "<OPTION>Basil Rathbone"

echo "<OPTION>Demi Moore"

echo "<OPTION>Lauren Bacall"

echo "<OPTION>Sean Connery"

echo "</SELECT>"

echo "<BR><BR>"

# имена переменных флажков 'view_cine' и 'view_vid'

echo "Do you watch films at the..<BR>"

echo "<INPUT TYPE="Checkbox" NAME=view_cine> Cinema"

echo "<INPUT TYPE="Checkbox" NAME=view_vid> On video"

echo "<BR><BR>"

# результаты ввода, присвоенного переменной 'textarea'

echo "Tell what is your best film, or just enter some comments<BR>"

echo "<TEXTAREA COLS="30" ROWS="4" NAME="textarea"></TEXTAREA>"

echo "<BR><INPUT TYPE=Submit VALUE="Send it">"

echo "<INPUT TYPE="reset" VALUE="Clear Form">"

echo "</FORM>"

echo "</BODY>"

echo "</HTML>"

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

После выполнения изменения в конструкции FORM ACTION получится обобщенный декодер форм. Для осуществления считывания из стандартного потока ввода можно использовать команду cat. Ниже показана конструкция, которую следует добавить в сценарий conv.cgi, в результате чего появится возможность использования методов get и post.

if ["$REQUEST_METHOD"="POST"]; then

QUERY_STRING=`cat -`

fi

Обратите внимание на то, что команда cat содержит дефис, благодаря чему эту команду можно применять для считывания данных из стандартного потока ввода.

При использовании метода post осуществляется обычная проверка значения переменной QUERY_string. ЗаPOSтем все символы, поступающие из стандартного потока ввода, присваиваются переменной QUERY_STRING. В этой ситуации возможно использование метода get, поскольку в любом случае требуется получить информацию из переменной querY_string.

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

/usr/lib/cgi-bin$ vim conv.cgi

#!/bin/sh

#сценарий conv.cgi

#декодирование строки URL

echo "Content-type: text/html"

echo ""

echo "<HTML><PRE>"

#если это post ???

if [ "$REQUEST_METHOD"="POST" ]; then

QUERY_STRING=`cat -`

fi

#отображение метода кодированной строки

echo "Method : $REQUEST_METHOD"

echo "Query String : $QUERY_STRING"

echo "<HR>"

#применение редактора sed для замены символов & символами табуляции

LINE=`echo $QUERY_STRING | sed 's/&/ /g'`

for LOOP in $LINE

do

# разбивка на поля NAME и TYPE, замена всех символов пробелами, a %hex_num -> \xhex_num

#замена всех символов "+" пробелами

NAME=`echo $LOOP | sed 's/=/ /g' | awk '{print $1}'`

TYPE=`echo $LOOP | sed 's/=/ /g' | awk '{print $2}' | \

sed -e 's/%\(\)/\\\x/g' | sed 's/+/ /g'`

#используется функция printf, которая отображает значения переменных

#после завершения преобразований шестнадцатеричных значений

printf "${NAME}=${TYPE}\n"

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

#передаются команде eval, благодаря чему отдельные поля можно адресовать

#при этом, если поля содержат пробелы, требуется удвоенная обратная косая черта

VARS=`printf "${NAME}=\\${TYPE}\n"`

eval `printf $VARS`

done

echo "<HR>"

if [ "$contact" != "" ]; then

printf "Hello $contact, it's great to meet you\n"

else

printf "You did not give me your name… no comment !\n"

fi

if [ "$film" != "-- Pick a Film --" ]; then

printf "Hey I agree, $film is great film\n"

else

printf "You didn't pick a film\n"

fi

if [ "$actor" != "-- Pick Your Favourite Actor --" ]; then

printf "So you like the actor $actor, good form!\n"

else

printf "You didn't pick a actor from the menu\n"

fi

if [ "$view_cine" = "on" ]; then

printf "Yes, I agree the cinema ls still the best place to watch a film\n"

else

printf "So you don't go to the cinema, do you know what you're missing\n"

fi

if [ "$view_vid" = "on" ]; then

printf "I like watching videos at home as well\n"

else

printf "No video!!. you're missing out on all the classics to rent or buy\n"

fi

if [ "$textarea" != "" ]; then

printf "And here are your comments...: $textarea\n"

else

printf "No comments entered, so no comment !\n"

fi

#используется printf для отображения специальных символов в случае их наличия

# printf "Your name is : $contact\n"

# printf "Your choice of film is : $film\n"

# printf "Your choice of actor is : $actor\n"

# printf "You watch films at the cinema : $view_cine\n"

# printf "You watch films on video : $view_vid\n"

# printf "And here are your comments : $textarea\n"

echo "</PRE>"

echo "</HTML>"

В итоге:

Иной вариант заполнения формы:

В отличии от "get", метод "post", как можно заметить, не добавляет закодированную строку к адресу.

POST или GET?

Какой из двух методов следует использовать, если сервер поддерживает оба – и POST, и GET ? Некоторые рекомендации из пособия по HTML/XHTML (ст.368) ---> PDF:

    • Для наиболее быстрого получения результатов передачи маленьких форм с небольшим числом коротких полей посылайте методом GET.

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

    • Если у вас нет опыта в написании приложений, обрабатывающих формы со стороны сервера, применяйте GET. Лишние действия, связанные с чтением и декодированием параметров, передаваемых по методу POST, хотя и не слишком трудны, все же, возможно, не заслуживают того, чтобы с ними связываться.

    • Если защищенность данных представляется важной, используйте POST. GET помещает параметры формы прямо в URL приложения, где они могут быть легко перехвачены сетевыми анализаторами пакетов или выделены из регистрационного журнала сервера. Если параметры содержат секретную информацию, такую как номер кредитной карты, вы можете нанести вред своим пользователям.Хотя у POST приложений есть свои огрехи в обеспечении безопасности, они во всяком случае могут воспользоваться шифровкой параметров, передаваемых в отдельном сеансе связи с сервером.

    • Если вы хотите вызвать находящееся за пределами форм серверное приложение, требующее передачи ему параметров, используйте GET, поскольку он позволяет включить в URL приложения параметры тем же способом, что и параметры формы. Приложения типа POST, напротив, ожидают дополнительной передачи данных от броузера после URL, чего нельзя достичь, употребляя традиционный тег <a>.

Практическое применение сценария cgi

Это будет отчет какой-то компании, именуемой Wonder Gifts.

Положим возникла задача, регулярно cоздавать отчет, который основан на запросе пользователя.

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

Задача отчета выполнить дополнительную обработку, которая заключается в суммировании месячных продаж товаров по кварталам, данные по которым хранятся в некой базе в нашем случае в файле. Результаты могут выводиться на экран, принтер либо на экран и принтер одновременно. Файл отчета содержит номера различных товаров, проданных в каждом квартале . Номера товаров соответствуют отделам Stationery, Books и Gifts. В данном случае форма будет содержать два раскрывающихся меню и переключатель. Одно меню предназначено для выборки по кварталам, второе — для выборки по отделам. Переключатель служит для выбора устройства вывода. В нашем примере отчет выводится только на экран; переключатели выполняют демонстрационную роль. Создадим файл данных, содержащий сведения о продаже по кварталам. В нем имеются следующие поля: отдел, год, квартал, и количество различных товаров, положим его в /home/httpd/cgi-bin/.....к примеру.

$ cat > qtr.txt

STAT 1998 1st 7998 4000 2344 2344

BOOKS 1998 1st 3590 1589 2435 989

GIFTS 1998 1st 2332 1489 2344 846

STAT 1998 2nd 8790 4399 4345 679

BOOKS 1998 2nd 889 430 2452 785

GIFTS 1998 2nd 9822 4822 3555 578

STAT 1998 3rd 8911 4589 2344 8690

BOOKS 1998 3rd 333 1489 6322 889

GIFTS 1998 3rd 2310 1483 3443 778

STAT 1998 4th 9883 5199 2344 6456

BOOKS 1998 4th 7333 3892 5223 887

GIFTS 1998 4th 8323 4193 2342 980

^C

$ chmod 666 qtr.txt

$ mv qtr.txt /home/httpd/cgi-bin/

$

Сценарий формы:

$ cat > gifts.cgi

#!/bin/sh

# сценарий gifts.cgi используется POST

# кирилица

echo "Content-type:text/html; charset=utf-8"

echo ""

echo "<HTML>"

# еще кирилица (на всякий случай, должно хватить и верхнего)

echo "<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />"

echo "<BODY>"

# gifts_result.cgi используется для обработки и вывода этой формы

echo "<FORM action="/cgi-bin/gifts_result.cgi" METHOD=POST>"

echo "<P>"

echo "<HR>"

echo "<H1><CENTER>LINUX & UNIX Shell Programming by David Tansley<BR>"

echo "КВАРТАЛЬНЫЙ ОТЧЕТ</H1></CENTER>"

echo "</P><HR>"

echo "Department:<SELECT NAME=dept>"

echo "<OPTION>GIFTS"

echo "<OPTION>STATIONERY"

echo "<OPTION>BOOKS"

echo "</SELECT>"

echo "Quarter End:<SELECT NAME=qtr>"

echo "<OPTION>1st"

echo "<OPTION>2nd"

echo "<OPTION>3rd"

echo "<OPTION>4th"

echo "</SELECT>"

echo "<BR><BR>"

echo "Отправить на:<BR>"

echo "<INPUT TYPE="radio" NAME=stdout VALUE=Printer >Printer"

echo "<INPUT TYPE="radio" NAME=stdout VALUE=Screen CHECKED>Screen"

echo "<INPUT TYPE="radio" NAME=stdout VALUE=Both >Both"

echo "<BR><BR><HR>"

echo "<INPUT TYPE=Submit VALUE="Send it">"

echo "<INPUT TYPE=Reset VALUE="Clear">"

echo "</FORM>"

echo "</BODY>"

echo "</HTML>"

^C

$ chmod 755 gifts.cgi

$ mv gifts.cgi /usr/lib/cgi-bin/

$

Переменной dept присваивается выбранное значение для отдела; переменной qtr присваивается номер выбранного квартала. Переменной stdout присваивается значение "printer", "screen" или "both"; в качестве значения по умолчанию выбирается screen (это значение указывается с помощью слова "CHECKED"). Ниже приведен сценарий, обрабатывающий полученную информацию.

$ cat > gifts_results.cgi

#!/bin/sh

#сценарий gifts_result.cgi

#Декодирование строки URL

echo "Content-type:text/html"

echo ""

echo "<HTML><PRE>"

# это post ???

if [ "$REQUEST_METH0D"="POST" ]; then

QUERY_STRING=`cat -`

fi

# декодирование

# используется sed для замены & символом табуляции

LINE=`echo $QUERY_STRING | sed 's/&/ /g'`

for LOOP in $LINE

do

NAME=`echo $LOOP | sed 's/=/ /g' | awk '{print $1}'`

TYPE=`echo $LOOP | sed 's/=/ /g' | awk '{print $2}' | \

sed -e 's/%\(\)/\\\x/g' | sed 's/+/ /g'`

# используется printf при выполнении шестнадцатеричных преобразований

VARS=`printf "${NAME}=\\${TYPE}\n"`

eval `printf $VARS`

done

echo "<HR>"

echo "<H1><CENTER> GIFTS Inc</CENTER></H1>"

echo "<H2><CENTER> Quarter End Results </CENTER></H2>"

echo "<HR>"

#нужно изменить имена полей со STATIONERY на STAT

#для осуществления корректного поиска

if [ "$dept" = "STATIONERY" ]; then

dept=STAT

fi

# считывание из файла qtr.txt

TOTAL=0

while read DEPT YEAR Q P1 P2 P3 P4

do

if [ "$DEPT" = "$dept" -a "$Q" = "$qtr" ]; then

TOTAL=`expr $P1 + $P2 + $P3 + $P4`

fi

continue

done<"/home/httpd/cgi-bin/qtr.txt"

echo "<H2>"

echo "<CENTER>TOTAL ITEMS SOLD IN THE $dept DEPARTMENT</CENTER>"

echo "<CENTER>is $TOTAL IN THE $qtr QUARTER</CENTER>"

echo "</H2><HR>"

# куда будет выведен отчет

if [ "$stdout" = "Both" ]; then

echo "This report ls going to the printer and the screen"

else

echo "This report ls going to the $stdout"

fi

echo "</PRE>"

echo "</HTML>"

^C

$ chmod 755 gifts_results.cgi

$ mv gifts_results.cgi /usr/lib/cgi-bin/

$

Первая часть сценария является общей для любой формы, обработка которой осуществляется с помощью метода post. Поскольку отсутствуют шестнадцатеричные значения для преобразования (так как поля ввода являются предопределенными опциями меню), нет нужды в использовании функции printf, но особого смысла в том, чтобы отказаться от использования этой команды, нет. Содержательная часть сценария выполняет считывание из файла qtr.txt. Цикл while осуществляет считывание и присваивание значений полей переменным DEPT, YEAR, Q, P1, Р2, P3, Р4 соответственно. Затем выполняется проверка значения переменной $dept (значение, отправленное пользователем) и переменной dept; результат конкатенируется с результатом другой проверки с помощью оператора AND. Если значение переменной $qtr (значение, отосланное пользователем) равно значению переменной Q, имеет место соответствие. Все числа, содержащиеся в сравниваемой строке, добавляются вместе.

В итоге в нашем распоряжении имеется сценарий формы и сценарий предназначенный для обработки информации, пересылаемой формой, результат: http://<имя_сервера>/cgi-bin/gifts.cgi или ссылка в файле main.shtml.

Поскольку разговор ведется о создании динамических Web-страниц, следует предусмотреть возможность заполнения списков или таблицы текущими данными, выбранными из существующего файла, вместо того, чтобы жестко кодировать эти данные в сценариях cgi. Для этого можно использовать цикл while который будет построчно считывать данные из файла, в нашем случае это будет /var/temp/list, по известным причинам размещение файла не должно быть в корневом каталоге Web-сервера. Для заполнения списка используется следующий код: echo "<OPTION>$LINE" Выбранный элемент присваивается переменной menu_selection.

$ cat > populat.cgi

#!/bin/sh

#сценарий populat.cgi

#заполнение раскрывающегося списка значениями из текстового файла

echo "Content-type: text/html"

echo ""

echo "<HTML>"

echo "<BODY>"

echo "<H4> CGI FORM populat.cgi populate pull-down list from a text file</H4>"

echo "<SELECT NAME=menu_selecflon>"

echo "<OPTION> - PICK AN OPTION - "

# считывание значений из файла для заполнения опций списка

while read LINE

do

echo "<OPTION>$LINE"

done </var/temp/list

echo "</SELECT>"

echo "</FORM>"

echo "</BODY>"

echo "</HTML>"

^C

$ chmod 755 populat.cgi

$ sudo mv populat.cgi /usr/lib/cgi-bin/

$

Создадим файл со значениями меню:

$ cat > list

zzzz

xxxxxx

ccccccc

vvvvvvvv

^C

$ chmod 666 list

$ mv list /var/temp

$

В итоге:

Автоматическое обновление Web–страницы

user@Debian8:~$ df

Файловая система 1K-блоков Использовано Доступно Использовано% Cмонтировано в

/dev/loop0 15350768 9289300 5258652 64% /

none 492 0 492 0% /dev

tmpfs 152808 116 152692 1% /run

tmpfs 5120 0 5120 0% /run/lock

tmpfs 445640 0 445640 0% /run/shm

cgroup 12 0 12 0% /sys/fs/cgroup

cgmfs 100 0 100 0% /run/cgmanager/fs

tmpfs 117968 0 117968 0% /run/user/999

tmpfs 117968 0 117968 0% /run/user/1000

user@Debian8:~$

Сценарии cgi в силу простоты создания и привлекательность Web-интерфейса удобны для многочисленных задач по обработке информации, мониторинга, запросам к базам данных и множества других задач, вопрос в задачах и фантазии, не обладая глубокими познаниями в HTML/Perl..., без особых проблем возможно создание удобных инструментов для своей работы и работы компании. При использовании cgi для сценариев, выполняющих функции мониторинга, часто необходимо выполнять обновление страницы в непрерывном режиме, ниже приводится сценарий выполняющий мониторинг файловой системы некого условного, например сервера:

$ cat > dfspace.cgi

#!/bin/sh

# сценарий dfspace.cgi

echo "Content-type: text/html"

echo ""

# автоматическое обновление каждые 60 секунд

echo "<meta http-equiv="Refresh" content=60;URL="http:/cgi-bin/dfspace.cgi">"

echo "<HTML>"

echo "<HR>"

echo "<A NAME="LINUX. PC Filesystems">LINUX. PC Filesystems</A>"

echo "<TABLE align="center" cellspacing="20" border=4 width="40%"

cols="2">"

echo "<TH align="center"> Capacity % </TH>"

echo "<TH align="center"> File System </TH>"

# получение вывода из df, но сначала фильтруется нужная информация!

df | sed 1d | awk '{print $5"\t"$6}' | while read percent mount

do

echo "<TR><TD align="center"><B>$percent</B></TD><TD align="center"><A>$mount</A></TD></TR>"

done

echo "</TABLE>"

echo "<PRE>"

echo ""

echo "</PRE>"

echo `uname -n` on ProxmoxVE/LXC "&ensp;" `date`

echo "<HR>"

echo "</HTML>"

^C

$ chmod 755 dfspace.cgi

$ sudo mv dfspace.cgi /usr/lib/cgi-bin/

$

Разбирая скрипт, обращаем внимание на тег: echo "<meta http-equiv="Refresh" content=60;URL="http:/cgi-bin/dfspace.cgi">" , который вызывает выполнение сценария каждые 60 секунд (в нашем случае). Ключевым словом является слово "Refresh", посредствам него Web-сервер понимает, что страницу надо загрузить по новой, а строка: content=60 задает время между загрузками. Сценарий использует часть вывода df и отображает файловую систему, поля 5-6.

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

echo "<TABLE align="center" cellspacing="20" border=4 width="40%" cols="2">"

echo "<TH align="center"> Capacity % </TH>"

echo "<TH align="center"> File System </TH>"

Параметр cellspacing устанавливает расстояние между внутренними и внешними границами таблицы. Параметр border хранит число, определяющее толщину табличной рамки. Параметр cols определяет количество столбцов в таблице. Ниже приведена основная часть описываемого сценария.

df | sed 1d | awk '{print $5"\t"$6}' | while read percent mount

do

echo "<TR><TD align="center"><B>$percent</B></TD><TD align="center"><A>$mount</A></TD></TR>"

done

Выполняется команда df , далее канал в sed для удаления заголовка, затем выполняется перенаправление к awk и считывание в пятом и шестом столбцах. Результаты присваиваются переменным percent и mount. "Сервер" поднят на контейнере LXC/ProxmoxVE , по этому структура файловой системы выглядит несколько не привычно, с первого взгляда.

Аббревиатура TR обозначает строку таблицы, a TD - табличные данные. Тем самым определяется место, куда направляется информация.

Памятка HTML/FORMS

Оптимальным вариантом будет использование пособия по HTML/XHTML (ст.368) ---->PDF, или что либо подобного, книга посвящена HTML4 и местами устарела, но только местами.

http://mathscinet.ru/manual/samples/cgi/cgi.html#password

http://www.edu.severodvinsk.ru/after_school

http://sozdatisite.ru/php/sozdanie-formy-registratsii-i-avtorizatsii-v-php.html

http://www.orenport.ru/images/img/1279/3.html

https://metanit.com/web/php/3.1.php

https://djbook.ru/rel1.7/topics/forms/index.html

http://alfalavista.ru/html <<-------------


А ниже приводится "не глубоко профессиональный взгляд" на создание форм в HTML:

В HTML документ форма вставляется при помощи тегов <FORM>....</FORM>, между которыми помещаются теги, определяющие элементы управления.

У тега <FORM> есть несколько параметров:

Параметр ACTION, который указывает URL CGI приложения взаимодействующее с формой.

Параметр METHOD, который укажет метод используемый для передачи данных из формы в CGI приложение (скрипта).

Этот параметр может принимать два значения: GET и POST, разница между ними состоит в том, что при значении GET вся информация помещается в переменную среды имя которой QUERY_STRING, а при значении POST CGI приложение получит все данные через stdin, и так как в этом случае не возможно сказать сколько информации будет передано, то используется переменная среды CONTENT_LENGTH, для задания количества информации, которое необходимо считать из stdin

Элементы управления.

Элемент вставляется с помощью тега <INPUT>.

Параметр TYPE задает тип элемента:

Параметр RADIO создает переключатели, элементы зависимые друг от друга.

(CHECKBOX предназначен для создания флажков)

Параметр TEXT используется для ввода текстовой информации.

(Размеры определяются параметрами SIZE и MAXLENGTH)

Параметр PASSWORD идентичен(почти) TEXT и предназначен для ввода пароля, отображает вводимую информацию в скрытом виде, заменяя содержимое звездочками.

Кнопки.

BUTTON обычная кнопка.

RESET кнопка сбрасывающая все введенные данные во всех органах управления, возвращая их к начальному состоянию, заданному при помощи параметра VALUE.

SUBMIT отсылает все данные из заполненной формы CGI приложению.

Для "красоты" помимо тривиальной кнопки для отправки данных можно использовать изображение, для этого параметру TYPE приписывается значение IMAGE (данные указываются как при вставке обычного графического изображения)

Параметр NAME задает имя элемента управления, которое будет посылаться программе обработчику.

Параметр VALUE задает начальное значение элемента управления (к примеру: текст по умолчанию для строки текстового ввода)

Параметр SIZE указывает ширину поля ввода для текстовых элементов управления.

Параметр MAXLENGTH максимальное количество символов которое можно ввести в это поле.

Для различных переключателей RADIO и флажков CHECKBOX, существует параметр CHECKED, указывающий, что данный элемент необходимо отметить как включенный, так же для этой пары управляющих элементов есть особенность в применении параметра NAME, состоящая в следующем:

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

Параметр ALIGN занимается выравниванием текста расположенного около формы.

Для графического изображения TYPE=IMAGE используется параметр SRC указывающий расположение графического файла.

Помимо тега <INPUT>, можно использовать тег <SELECT>...</SELECT>, применяемый для создания выпадающих списков, имеет два параметра:

NAME и SIZE, имя и высота списка в строках, соответственно (<SELECT NAME=menu_selecflon>, в примере заполнения списков или таблицы текущими данными, выбранными из существующего файла). Строки входящие в выпадающий список выбора предваряемые тегом <OPTION> помещаются внутри тега. Для отметки строки выбираемой по умолчанию используется тег <OPTION SELECTED>

Тег <TEXTAREA>...</TEXTAREA> создают поле для много строчного ввода текста, у него есть параметр NAME и добавлены параметры: ROWS и COLS, задающие размер поля ввода по вертикали и горизонтали в строках и символах соответственно

Наверное следует сказать, что CGI в "чистом" виде закончил свой век (на production) в силу упомянутых недостатков и скорости работы, давно пришло время FastCGI, где принципы создания скриптов в отличии от принципов работы "почти не изменились", но и в чистом виде CGI вполне пригоден для выполнения локальных задач. Однако "почти не изменились" не относится к shellscript, поскольку весь смысл FastCGI заключается в том, чтобы избежать появления нового процесса для каждого входящего соединения, а по самой природе языка, сценарий оболочки порождает множество процессов во время его выполнения, и как результат нет: cat, awk, sed, grep и т.д , поэтому если вы собираетесь использовать shellscript, ни чего выдающегося , скорее всего, не получится но можно использовать обычный CGI вместо FastCGI. Оптимальным вариантом будет наверное: PHP в режиме FastCGI, PHP-FastCGI Process Manager. FastCGI это круто, это быстро, это безопасно, и "даже" Apache/Server , после легкой заточки способен осознать этот протокол, однако все используют Nginx, который совместим более чем полностью. http://ru.bmstu.wiki/FastCGI