Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

CGI-программирование с самого начала


Уважаемые подписчики!

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

Для тех, кто подписался на эту рассылку недавно, и для кого это первый выпуск, напоминаю, что предыдущие выпуски рассылки вы можете посмотреть в архиве рассылки на subscribe.ru

Обработка ошибок при открытии файлов (окончание)

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

Но всегда ли этот способ является оптимальным?

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

Все файлы, которые скрипты используют в процессе работы, можно разделить на две большие категории:

  • Файлы, которые необходимы для работы скрипта в их начальном виде, т.е. в том, в котором они были размещены на сервере в процессе установки скрипта. Как правило, содержимое этих файлов в случае их отсутствия или повреждения не может быть восстановлено "силами" самого скрипта, а поскольку они ему необходимы для нормальной адекватной работы, то генерация фатальной ошибки является самым удачным способом реагирования на ошибки при работе с ними. В качестве примера можно привести файлы шаблонов вывода скрипта, файлы настроек и т.п. Содержимое этих файлов, как правило, не меняется в процессе работы скрипта;

  • Файлы, в которых скрипт хранит свои данные, т.е. осуществляет как чтение, так и запись их содержимого. Примером могут служить файл сообщений гостевой книги, файл счетчика посетителей, в котором хранится и накапливается количество посещений и т.п. Особенностью этих файлов является то, что в случае их отсутствия они могут быть созданы скриптом в их изначальном, "нулевом" виде.

    Скажем, если счетчик посетителей, будучи запущен, не найдет своего файла данных с нужным именем, он может создать новый файл данных со значением 1; в этом случае, скажем, удаление файла данных приведет к сбросу счетчика посещений, но не к потере его работоспособности.

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

    Однако даже в случае такой "интеллектуальности" придется предусмотреть вариант фатальной ошибки - ведь ошибка при открытии файла может означать не только его отсутствие, а и, например, неверно выставленные права доступа к нему.

    Хотя надо сказать, что такая ситуация в реальности маловероятна, т.к. обычно по умолчанию файлы создаются на сервере с правами доступа rw-r--r-- (644), т.е. владельцу файла сразу разрешены и чтение, и запись его содержимого, а интерпретатор Perl запускается от имени владельца файлов эккаунта; поэтому самыми распространенными ошибками при установке скриптов все же являются отсутствие файла, неверный регистр символов в его имени и т.п., а это все может быть решено созданием "нулевого" файла с нужным именем. Но такая ситуация в принципе возможна.

    Поэтому, на мой взгляд, оптимальной алгоритмикой будет такая:

  • попытка открыть файл;

  • в случае возникновения ошибки - попытка создать файл;

  • если опять возникла ошибка - генерация фатальной ошибки.
  • Как это организовать практически?

    Самый простой вариант - фрагмент кода, где файл открывается для дописывания:

    open DATA, ">>data.txt";

    Дело в том, что в данном случае при отсутствии файла функция open сама создаст "нулевой" файл с нужным именем, и лишь в случае невозможности это сделать - возвратит ошибку, которую уже можно обрабатывать как фатальную:

    (open DATA, ">>data.txt") || (die "cannot open data.txt for append!");

    Чуть сложнее обстоит дело с кодом, открывающим файл на чтение:

    if (!open DATA, "<data.txt") {
    
    # Создаем, если возможно, data.txt, и уже его открываем на чтение
    
    (open DATA, ">data.txt")||(die "cannot create data.txt!");
    close DATA;
    (open DATA, "<data.txt")||(die "unexpected error using data.txt!")
    };
    

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

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

    if (!open DATA, "<data.txt") {
    (open DATA, ">data.txt")||(die "cannot create data.txt!");
    print DATA "1"; # Записываем начальное значение в файл
    close DATA;
    (open DATA, "<data.txt")||(die "unexpected error using data.txt!")
    };
    

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

    (open DATA, ">data.txt") || (die "cannot open data.txt for output!");

    На этом мы заканчиваем эту, на мой взгляд, несколько скучноватую тему обработки ошибок при работе с файлами. :-)

    Следующий выпуск будет посвящен многочисленным функциям Perl для работы с файлами и каталогами.

    В заключение напоминаю Вам, что на сайте нашей рассылки http://www.cgi-scripts.info/ Вы можете найти статьи по CGI-программированию, а также коллекцию готовых бесплатных CGI-скриптов, которые Вы можете использовать на своих сайтах.

    А на другом нашем сайте, http://www.angel07.webservis.ru/< /B> Вы найдете материалы по хостингу, в частности - статьи по вопросам хостинга и описание нескольких хороших предложений платного хостинга.

    На сегодня все. До скорой встречи!

    Успехов!


    Андрей
    angel07@inbox.ru

    В избранное