FreeBSD

Основы модуля mod_rewrite Apache

Модуль mod_rewrite является программным модулем веб сервера Apache (обратите внимание, что он не будет выполняться под другими веб-серверами). Его первичная функция — манипуляция действий с URL. Модуль очень универсален и разносторонен, поэтому я постараюсь
показать здесь множество реальных примеров.

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

Однако нужно быть очень осторожным и даже дотошным при работе с этим модулем! Некоторые ошибки, которые Вы способны допустить, могут привести к логической петле, причиняя непрекращающуюся 100%-ую загрузку ценрального процессора (CPU).

Чтобы не казаться пространным в рассуждениях, приведу некоторые очень простые примеры.

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

Есть несколько способов проверить это:

  1. Спросить вашего системного администратора — знает ли он (или она) о наличии этого модуля на веб сервере. Они действительно должны знать, но как показывает практика — попадаются и не очень сведующие сисадмины. Не напрягайте других: если Вы используете ваш веб сервер с сотнями других доменов, ваши действия могут разбудить некоторых спящих
    собак, поскольку использование mod_rewrite будет всегда влечь за собой некоторую увеличенную загрузку ценрального процессора.
  2. Проверить ваш файл конфигурации Apache (httpd.conf), если вы имеете к нему доступ. Один из возможных стандартных путей может быть: /etc/httpd/httpd.conf. Однако, ваш путь может очевидно отличаться от этого.
  3. Проверить работу вашего сервера с нижеприведенными примерами. Если
    сервер работает без ошибок — mod_rewrite действительно установлен на вашей системе. Если нет, Вы получите следующее сообщение при запросе любой web-страницы с вашего сервера: «Внутренняя ошибка сервера». Также, вы увидите такую запись в файле «error.log»:
    «Invalid command RewriteEngine, perhaps mis-spelled or defined by a module not included in the server configuration».

Теперь давайте копнем поглубже и посмотрим первый практический примерчик.

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

Для нашего примера потребуется использование файла .htaccess. Для работы этого метода, вы должны загрузить файл под названием «.htaccess» (пожалуйста, обратите внимание на точку в начале имени файла!) в папку сервера, с которой Вы будете работать. Это можно сделать через telnet или ftp. (Предупреждение: .htaccess должен быть загружен в ‘режиме ASCII’, то есть не в двоичном режиме!)

Если у Вас уже имеется файл «.htaccess», например со следующими записями:

Options Includes +ExecCGI
AddType text/x-server-parsed-html .html

то просто добавьте снизу наш образец кода к уже существующему (важно: редактируйте ваш файл .htaccess в ASCII-редакторе типа Notepad).

Первые две записи запустят сам модуль:

RewriteEngine on
Options +FollowSymlinks

Совет: запись «RewriteEngine off» отменит все последующие команды. Это
очень полезная особенность — вместо необходимости комментировать все
последующие строки — все, что Вы должны сделать, это установить «off».

Если ваш системный администратор запрещает Вам использование «Options
+FollowSymlinks», Вы не сможете ограничить использование mod_rewrite
для отдельных каталогов, вместо этого изменения будут действовать на
весь сервер.

Следующая необходимая запись:

RewriteBase /

«/» является корневым (основным) URL. Если у вас какой-то другой URL, то вы можете указать это в данной директиве, однако «/» — обычно эквивалентно адресу «http://домен.ru».

А теперь, господа, перейдем к более интересным записям!

Предположим, что вы хотите защитить от несанкционированного доступа
ваш файл .htaccess. На некоторых серверах вы можете легко читать этот
файл просто вводя URL следующего формата в поле адреса вашего
браузера: http://www.domain.com/.htaccess — серьезное упущение защиты,
так как содержание вашего .htaccess может показать важную информацию
об установках и настройках вашего сайта человеку, знающему как эти
знания применить против вас.

Чтобы блокировать этот доступ, запишем следующее:

RewriteRule ^.htaccess$ - [F]

Это правило переводится так:

Если кто-то пробует обращаться к файлу .htaccess, система должна выдать код ошибки «HTTP response of 403» или «403 Forbidden — You don’t have permission to access /.htaccess on this server».

Конструкция ^.htaccess$ в этом регулярном выражении означает:

  • ^ — якорь начала строки;
  • $ — якорь конца строки;
  • . — в регулярных выражениях точка «.» обозначает мета-символ и должна быть защищена обратным слэшем (backslash), если вы все-таки хотите использовать именно фактическую точку.
  • Имя файла должно быть расположено точно между начальным и конечным якорем. Это будет гарантировать то, что только это определенное имя файла и никакое другое, сгенерирует код ошибки.
  • [F] — специальный «запрещающий» флажок (forbidden).

В этом примере, файл «.htaccess» теперь будет состоять из таких строк:

RewriteEngine on
Options +FollowSymlinks
RewriteBase /
RewriteRule ^.htaccess$ - [F]

Если мы добавим наш код (в примерах) к существовавшему ранее файлу «.htaccess», то получим следующую конструкцию:

Options Includes +ExecCGI
AddType text/x-server-parsed-html .html
RewriteEngine on
Options +FollowSymlinks
RewriteBase /
RewriteRule ^.htaccess$ - [F]

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

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

Синтаксис: условие должно предшествовать правилу!

Возьмем еще один пример (запись в файле .htaccess):

RewriteEngine on
Options +FollowSymlinks
RewriteBase /
RewriteCond %{HTTP_USER_AGENT} ^EmailSiphon
RewriteRule ^.*$ - [F]

Назначение первых трех записей было подробно разобрано в первой части публикации. Их функция — включение «движка перезаписи», то есть самого модуля.

Последние две строки запрещают доступ поисковому роботу под кодовым названием «EmailSiphon» (имеется ввиду имя пользовательского агента). Данный робот является сборщиком почтовых адресов с различных веб страниц.

Строка:

RewriteCond %{HTTP_USER_AGENT} ^EmailSiphon

состоит из трех частей:

  • Директива (указание): RewriteCond;
  • Проверочная строка: %{HTTP_USER_AGENT};
  • Образец условия: ^EmailSiphon.

Проверочная строка — переменная сервера, которая может быть записана в общей форме: ‘% {ИМЯ_ПЕРЕМЕННОЙ}’.

Образец условия — регулярное выражение. Для более полного понимания темы стоит рассмотреть регулярные выражения как класс.

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

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

Например, регулярное выражение:

s/abc/xyz/g

заменит строку ‘abc’, на строку ‘xyz’ во всем тексте.

Вот краткий обзор наиболее важных элементов с некоторыми примерами:

  • . (точка) — текст (любой символ);
  • | — чередование (то есть/abc|def/);
  • * — квантификатор (разрешено любое число);
  • ^ $ — якоря строки;
  • s — оператор (string1 заменить на string2);
  • g — модификатор (искать по всему тексту).

Регулярные выражения конструируются с помощью этих элементов и других
«обычных» символов. Они не являются отдельным языком, а используются другими средствами, например языками программирования типа Perl или PHP, а также текстовыми редакторами (Emacs).

Если говорить о связи регулярных выражений и модуля mod_rewrite, то они используются в директивах RewriteRule и RewriteCond.

«^» обозначает начало строки. Из этого следует, что User-agent должен начинаться со строки «EmailSiphon» и ни с чего другого («NewEmailSiphon», например, не работал бы).

Но, поскольку данное регулярное выражение не содержит символ «$» (якорь конца строки), User-agent мог бы быть, например, «EmailSiphon2».

Последняя строка нашего примера:

RewriteRule ^.*$ - [F]

определяет, что именно нужно делать, когда робот запросит доступ.

Регулярное выражение ‘^.*$’ означает «Доступ ко всем файлам запрещен».

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

«*» означает то, что строка может встречаться неограниченное количество раз. В этом случае, независимо от имени запрошенного файла, будет выдана ошибка.

«EmailSiphon», конечно, не единственный почтовый сборщик. Другой известный член этого семейства — ‘ExtractorPro’. Допустим мы хотим запретить доступ и этому роботу. В таком случае нам необходимо еще одно условие.

Теперь файл .htaccess будет выглядеть так:

RewriteEngine on
Options +FollowSymlinks
RewriteBase /
RewriteCond %{HTTP_USER_AGENT} ^EmailSiphon [OR]
RewriteCond %{HTTP_USER_AGENT} ^ExtractorPro
RewriteRule ^.*$ - [F]

Третий аргумент [OR] (в первой строке RewriteCond) называется «флагом». Существуют два возможных флага:

NC — не учитывать регистр букв.
OR — означает «или следующее условие».

Флажок NC позволяет игнорировать регистр букв в искомом образце. Например:

RewriteCond %{HTTP_USER_AGENT} ^emailsiphon [NC]

Эта строка определяет, что и «emailsiphon» и «EmailSiphon» будут признаны как идентичные выражения.

Вы можете использовать сразу несколько флажков, разделяя их запятыми.

RewriteCond % {HTTP_USER_AGENT} ^EmailSiphon [NC, OR]
RewriteCond % {HTTP_USER_AGENT} ^ExtractorPro

Нет никаких ограничений по числу условий. Таким образом, Вы можете блокировать 10, 100, 1000 или более известных почтовых сборщиков. Определение этих 1000 условий — просто вопрос загрузки сервера и прозрачности файла «.htaccess».

В вышеупомянутом примере используется глобальная переменная «HTTP_USER_AGENT». Существуют также другие переменные:

  • REMOTE_HOST;
  • REMOTE_ADDR.

Например, если вы хотите заблокировать паука пришедшего с www.site.ru, вы можете использовать глобальную переменную «REMOTE_HOST» таким образом:

RewriteCond % {REMOTE_HOST} ^www.site.ru$
RewriteRule ^.*$ - [F]

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

RewriteCond % {REMOTE_ADDR} ^212.37.64.10$
RewriteRule ^.*$ - [F]

В регулярном выражении по проверке точного и полного IP-адреса нужно использовать начальные и конечные якоря. Также можно исключить целый диапазон:

RewriteCond %{REMOTE_ADDR} ^212.37.64.
RewriteRule ^.*$ - [F]

Этот пример показывает, как можно заблокировать диапазон IP адресов с 212.37.64.0 по 212.37.64.255.

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

RewriteCond %{REMOTE_ADDR} ^212.37.64
RewriteRule ^.*$ - [F]

Внимание, вопрос!

Если мы пишем в регулярном выражении «^212.37.64» вместо «^212.37.64.» (с точкой в конце), то даст ли это тот же самый эффект, и будут ли исключены те же самые IP адреса?

Вот решение задачки:

Если мы пишем в регулярном выражении «^212.37.64» вместо «^212.37.64.» (с точкой в конце), то даст ли это тот же самый эффект, и будут ли исключены те же самые IP адреса?

Регулярное выражение ^212.37.64 удовлетворяет и применимо к следующим строкам:

212.37.64
212.37.640
212.37.641
212.37.64a
212.37.64abc
212.37.64.12
212.37.642.12

Следовательно, последняя цифра «4» может сопровождаться любой символьной строкой. Однако, максимальным значением IP является адрес 255.255.255.255 который подразумевает, что например 212.37.642.12 неправильный (недопустимый) IP. Единственный допустимый IP в
вышеприведенном списке — 212.37.64.12.

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

http://www.yoursite.com/cgi-bin/shop.cgi?product1
http://www.yoursite.com/cgi-bin/shop.cgi?product2
http://www.yoursite.com/cgi-bin/shop.cgi?product3

Эти адреса представлены как ссылки на большинстве страниц сайта.

А теперь допустим, что вы решили добавить сайт для индексации в поисковые системы. Тут вас поджидает небольшая неприятность — не все поисковики принимают, понимают и индексируют URL, в которых содержится символ «?». Более естественным и приемлемым для поисковика является URL вида:

http://www.yoursite.com/cgi-bin/shop.cgi/product1

В данном случае символ ‘?’ заменяется на ‘/’. Еще более комфортабельный URL с точки зрения поисковика будет иметь вид:

http://www.yoursite.com/shop/product1

Для поисковика, «shop» теперь как-бы является директорией, содержащей товары product1, product2 и т.д.

Если пользователь, со страницы результатов запроса в поисковике проследует по такой ссылке, то эта ссылка должна будет трансформироваться в ссылку /shop.cgi?product1.

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

RewriteEngine on
Options +FollowSymlinks
RewriteBase /
RewriteRule ^(.*)shop/(.*)$ $1cgi-bin/shop.cgi?$2

Переменные $1 и $2 составляют так называемые обратные ссылки. Они связаны с текстовыми группами. Вызываемый URL разбивается на части. Все, что находится перед «shop», плюс все что находится после «shop/» определяется и хранится в этих двух переменных: $1 и $2.

До этого момента, наши примеры использовали ‘правила’ типа:

RewriteRule ^.htaccess*$ - [F]

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

Для нашей записи вида:

RewriteRule ^(.*)shop/(.*)$ $1cgi-bin/shop.cgi?$2

применяется общий синтаксис:

RewriteRule текущийURL перезаписываемыйURL

Как видите, эта директива выполняет действительную «перезапись» URL адреса.

В дополнение к записям в файл .htaccess, нужно еще заменить все ссылки на сайте, которые имеют формат «cgi-bin/shop.cgi?product», на ссылки вида «shop/product».

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

Таким образом вы можете превратить чисто динамический сайт в сайт, имеющий статическую структуру, что явно принесет пользу в вопросе индексирования различными посковыми машинами. Обратите внимание на вид URL адресов на данном сайте. Вдобавок ко всему, они имеют еще и
легкочитамую для человека структуру — ЧПУ (человекопонятный УРЛ). Но об этом мы поговорим в другой статье.

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

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

Однако, относительно запросов к файлу «robots.txt», предпочтительно иметь доступ ко всем этим данным, чтобы иметь больше информации о посещении поисковиков, чем просто знать их IP-дреса. Для того, чтобы оганизовать это, в «.htaccess» должны быть следующие записи:

RewriteEngine on
Options +FollowSymlinks
RewriteBase /
RewriteRule ^robots.txt$ /text.cgi?%{REQUEST_URI}

Теперь при запросе файла «robots.txt» наш RewriteRule переадресует посетителя (робота) к обрабатывающему запросы скрипту text.cgi. Кроме того, переменная передается скрипту, которая будет обработана в соответствии с вашими нуждами. «REQUEST_URI» определяет имя запрашиваемого файла. В данном примере это — «robots.txt». Скрипт прочтет содержание «robots.txt» и отправит его web-браузеру или роботу поискового сервера. Таким образом, мы можем считать хиты посетителей и вести свои лог-файлы.

С этой целью, скрипт будет использовать переменные окружения $ENV {‘HTTP_USER_AGENT’}’ и т.д. Это обеспечит получение всей требуемой информации. Вот исходный текст для сценария cgi, упомянутого выше (пример взят с сайта http://fantomaster.com):

#!/usr/bin/perl
# If required, adjust line above to point to Perl 5.
#################################
# (c) Copyright 2000 by fantomaster.com #
# All rights reserved. #
#################################
$stats_dir = "stats";
$log_file = "stats.log";
$remote_host = "$ENV{'REMOTE_HOST'}";
$remote_addr = "$ENV{'REMOTE_ADDR'}";
$user_agent = "$ENV{'HTTP_USER_AGENT'}";
$referer = "$ENV{'HTTP_REFERER'}";
$document_name = "$ENV{'QUERY_STRING'}";
open (FILE, "robots.txt");
@TEXT = ;
close (FILE);
&get_date;
&log_hits("$date $remote_host $remote_addr $user_agent $referer $document_name");
print "Content-type: text/plain
";
print @TEXT;
exit;
sub get_date {
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
$mon++;
$sec = sprintf ("%02d", $sec);
$min = sprintf ("%02d", $min);
$hour = sprintf ("%02d", $hour);
$mday = sprintf ("%02d", $mday);
$mon = sprintf ("%02d", $mon);
$year = scalar localtime;
$year =~ s/.*?(d{4})/$1/;
$date="$year-$mon-$mday, $hour:$min:$sec";
}
sub log_hits {
open (HITS, ">>$stats_dir/$log_file");
print HITS @_;
close (HITS);
}

Загрузите файл с данным содержимым в корневую или в DocumentRoot директорию сервера и установите права доступа у файлу (chmod) 755. Затем, создайте каталог «stats». Более детальное описание о том, как установить скрипт вы можете получить на сайте разработчика. Если настройки вашего сервера не позволяют исполнять cgi-сценарии в главной директории (DocumentRoot), то попробуйте следующий вариант:

RewriteRule ^robots.txt$ /cgi-bin/text.cgi?%{REQUEST_URI}

Обратите внимание, что в этом случае, будет необходимо изменить пути в коде скрипта!

Если вы хотите вести логи всех операций, выполненных с помощью mod_rewrite, можно активировать это с помощью следующей записи:

RewriteLog /usr/local/apache/logs/mod_rewrite_log
RewriteLogLevel 1

Эту строку нужно вписать в «Раздел 2: Конфигурация основного сервера» в файле httpd.conf, а не в .htaccess!

Все манипуляции, произведенные mod_rewrite будут записываться в этот файл. Имя лог файла может быть любым. Вы можете указать абсолютный или относительный (относительно ServerRoot) путь к файлу.

Если вы хотите вести разные лог файлы для различных виртуальных хостов, то нужно ввести изменения в «Раздел 3: Виртуальные сервера», например так:

ServerAdmin webmaster@yourdomain.com
DocumentRoot /usr/www/htdocs/yourdomain
ServerName yourdomain.com
RewriteLog /usr/apache/logs/yourdomain_mod_rewrite_log
RewriteLogLevel 1

RewriteLogLevel может быть определен в пределах от 1 до 8. Обычно достаточно первого уровня. Более высокие уровни используются для отладки.

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

cde2c920.infoseek.com spider
205.226.201.32 spider
cde2c923.infoseek.com spider
205.226.201.35 spider
cde2c981.infoseek.com spider
205.226.201.129 spider
cde2cb23.infoseek.com spider
205.226.203.35 spider

Ключи, как вы видите, имена хостов или IP-адреса. В этом простеньком примере значение всегда одно — «spider». Естественно, в реальном файле значения будут другие. Эта директива может быть записана во второй («Конфигурация основного сервера») или третий («Виртуальные сервера»)
раздел файла httpd.conf:

RewriteMap botBase txt:/www/yourdomain/spiderspy.txt</code>
 
Карта перезаписи возымеет эффект на весь сервер. Также, в файл .htaccess записывается:
 
<pre lang="ini">RewriteCond ${botBase:%{REMOTE_HOST}} =spider [OR]
RewriteCond ${botBase:%{REMOTE_ADDR}} =spider
RewriteRule ^(.*).htm$ $1.htm [L]
RewriteRule ^.*.htm$ index.html [L]</code>
 
Данные условия будут производить системную проверку: произведен ли запрос поисковиком. С этой целью производится поиск по файлу spiderspy.txt. Если ключ найден, будет возвращено значение «spider», а «условие» будет являться истинным.Затем выполняется первый RewriteRule. Это означает то, что запрашиваемая '.htm' страница будет отдана поисковику. Переменная $1 равна части в круглых скобках '^(. *).htm$', то есть имя файла останется тем же самым.
 
Если же URL вызван обычным посетителем, то применяется второе «правило»: пользователь будет перенаправлен на страницу «index.html».
 
Поскольку «.htm» страницы будут читаться только «пауками», они могут быть оптимизированы соответственно для поисковых серверов. Вы можете также использовать файл в формате «dbm»вместо обычного текстового файла. Бинарный формат данных позволяет ускорить поиск, который
является особенно важным, если вы работаете с очень большими списками поисковиков. Пример, данный выше, предлагает простые функциональные возможности клоакинга. Все обычные посетители будут всегда переадресовываться к странице index.html и не будет вестись никаких
логов файлов вне логов mod_rewrite.
 
Можно заменить несколько строчек кода php (perl и т.д.) в ваших приложениях, используя всего одну-две строки mod_rewrite. Последний пример проиллюстрирует это более подробно.
 
Цель — показать посетителям 'фото дня'. Посетитель, кликнувший по ссылке http://yoursite.com/pic.html увидит лучшую фотографию или картинку дня, и так каждый день. Мы будем работать с серверными переменными:
 
<pre lang="ini">TIME_MON
TIME_DAY</code>
 
Поместим в файл .htaccess одну единственную строку:
 
<pre lang="ini">RewriteRule ^pic.html$ pic-%{TIME_MON}-%{TIME_DAY}.html</code>
 
Запрашиваемый URL будет перезаписан, например:
 
<pre lang="ini">pic-08-28.html
pic-08-29.html
pic-08-30.html
и так далее.

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

By sysadmin on 24.02.2009 | FreeBSD, Linux
Метки: , , ,

Преобразование ссылок с помощью Apache (mod_rewrite)

Допустим, у вас есть работающий веб-сайт, состоящий из большого количества статических html-страниц. Все идет хорошо, но вдруг в какой-то момент вы решаете усовершенствовать работу веб-сайта и добавляете динамические скрипты: в результате страничка новостей теперь доступна по ссылке http://www.site.com/cgi-bin/news.cgi вместо прежней http://www.site.com/news.html, а каталог, в котором хранились страницы с описанием российских регионов, полностью перекочевал в динамику, и наш горячо любимый 77-й регион теперь доступен по неэстетично выглядящей ссылке http://site.ru/cgi-bin/regions.pl?region=77&mode=brief вместо легко запоминаемой http://site.ru/regions/77.html.

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

Анализ проблемы наводит на мысль о том, как хорошо было бы иметь возможность обращаться к одним и тем же страницам по различным HTTP-ссылкам, причем для страниц с похожими ссылками было бы очень удобно описать одно общее для них правило вместо того, чтобы для каждой страницы выписывать все возможные варианты ведущих на нее HTTP-ссылок. Если ваш веб-сайт работает под управлением весьма популярного в настоящее время веб-сервера Apache (скорее всего, это именно так), то в вашем распоряжении есть мощнейшее средство преобразования ссылок, которое реализуется специальным программным модулем mod_rewrite. Некоторые директивы данного модуля могут использоваться только в конфигурационном файле самого веб-сервера, другие же — в специальных файлах .htaccess, которые можно располагать в подкаталогах иерархии вашего веб-сайта. Именно эти директивы из .htaccess и производят основную работу по преобразованию ссылок, поэтому их мы опишем более подробно.

Для перестраховки можно уточнить у службы технической поддержки вашего хостера, включен ли модуль mod_rewrite в состав веб-сервера, обслуживающего ваш веб-сайт, и допускается ли использование его директив в файлах .htaccess. Поскольку данный модуль широко используется во многих проектах, каждый уважающий себя хостер на оба ваших вопроса ответит: «Да, конечно». Если же вы получили отрицательный ответ, это хороший повод задуматься о смене хостинг-провайдера на другого, предоставляющего более качественные услуги.

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

# Включение преобразования ссылок
RewriteEngine on
# Новостная страница
RewriteRule ^news.html$ /cgi-bin/news.cgi
# Страницы с описаниями регионов
RewriteRule ^regions/([0-9]+)\.html$ /cgi-bin/regions.pl?region=$1&mode=brief

Директива RewriteEngine включает или выключает преобразование ссылок (соответственно «RewriteEngine on» или «RewriteEngine off»). Действие директивы распространяется на текущий каталог и на все его подкаталоги, в которых нет своих файлов .htaccess с данной директивой.

Правила преобразования ссылок наследуются чуть сложнее. Чаще всего преобразование по умолчанию отключено в основном конфигурационном файле веб-сервера. Допустим, что вы записали в .htaccess некоего каталога директиву «RewriteEngine on» и некоторое количество правил преобразования. Перейдем теперь в один из подкаталогов. Если здесь нет файла .htaccess, либо в нем нет ни одной директивы модуля mod_rewrite, то все правила преобразования наследуются от родительского каталога. Если в файле .htaccess есть хотя бы одна директива модуля mod_rewrite, то не наследуется ничего, а состояние по умолчанию выставляется таким же, как в главном конфигурационном файле веб-сервера (по умолчанию «off»). Поэтому, если вы желаете иметь в этом каталоге свой набор правил преобразования, не забудьте добавить директиву «RewriteEngine on». Есть и третий вариант. Допустим, вы желаете унаследовать все правила из родительского каталога и добавить к ним несколько новых — для этого вам понадобится директива RewriteOptions, которая допускает только один фиксированный аргумент. Таким образом, в файл .htaccess вы должны записать ваши новые правила и две директивы: «RewriteEngine on» и «RewriteOptions inherit».

А теперь перейдем непосредственно к описанию правил. Преобразования описываются при помощи директивы RewriteRule. Правил может быть несколько, при этом все они применяются в порядке их описания. Когда правила заканчиваются, они вновь начинают применяться с самого начала, и этот цикл продолжается до тех пор, пока «срабатывает» хотя бы одно из правил. В некоторых случаях это может приводить к зацикливанию, поэтому при описании правил нужно быть предельно внимательным. Существует несколько специальных флагов, которые предоставляют возможность прервать этот процесс на определенном правиле или пропустить несколько правил (об этом будет рассказано ниже). Синтаксис директивы RewriteRule выглядит следующим образом:

RewriteRule «исходный путь» «замена» «флаги»

Исходный путь — это часть исходной ссылки, от которой отрезаны имя сервера, путь до текущего каталога и параметры запроса. Допустим, что ваш веб-сайт www.site.com расположен в каталоге /home/site/www. Тогда для ссылки http://www.site.com/test/list.html?mode=0 исходным путем в каталоге /home/site/www будет test/list.html, а в каталоге /home/site/www/test — list.html. Исходный путь задается регулярным выражением. Символ ! перед исходным путем означает, что правило «срабатывает» по несовпадению ссылки с заданным регулярным выражением.

Замена — это то, на что будет заменена исходная ссылка в случае «срабатывания» правила. Замена может быть относительной (если она не начинается с символа /) и абсолютной (если она начинается с символа / или представляет собой полную ссылку, начинающуюся с http:// или https://). В замене можно использовать определенные части исходного пути, отмеченные круглыми скобками. При этом макрос $1 обозначает ту часть исходного пути, которая расположена внутри первой пары скобок, $2 — внутри второй пары и так далее.

Флаги — это дополнительные опции для данного правила, которые перечисляются в квадратных скобках через запятую.

  • R (redirect) останавливает процесс преобразования и возвращает результат браузеру клиента как редирект на данную страницу (302, MOVED TEMPORARY). С данным флагом можно указать другой код результата, например «R=301» возвратит редирект с кодом 301 (MOVED PERMANENTLY).
  • F (forbidden) возвращает ошибку 403 (FORBIDDEN).
  • G (gone) возвращает ошибку 410 (GONE).
  • P (proxy) — по этому флагу Apache выполняет подзапрос (sub-request) к указанной странице с использованием программного модуля mod_proxy, при этом пользователь ничего не узнает об этом подзапросе. Если модуль mod_proxy не входит в состав вашей сборки Apache, то применение данного флага вызовет ошибку.
  • L (last) останавливает процесс преобразования, и текущая ссылка считается окончательной.
  • N (next) запускает процесс преобразования с первого по порядку правила.
  • C (chain) объединяет несколько правил в цепочку. Если первое правило цепочки «не срабатывает», то вся цепочка игнорируется.
  • NS (nosubreq) разрешает «срабатывание» правила только для настоящих запросов, игнорируя подзапросы (подзапрос может быть вызван, например, включением файла при помощи директивы SSI).
  • NC (nocase) отключает проверку регистра символов.
  • QSA (qsappend) добавляет исходные параметры запроса (query string) к замене. Если замена не включает в себя новые параметры запроса, то исходные параметры запроса добавляются автоматически. Если же включает, то без флага QSA исходные параметры запроса будут утеряны.
  • PT (passthrough) останавливает процесс преобразования и передает полученную новую ссылку дальше «по цепочке», чтобы над ней могли «поработать» директивы Alias, ScriptAlias, Redirect и им подобные (тогда как при флаге L новая ссылка считается окончательной и не подлежит дальнейшей обработке).
  • S (skip) пропускает следующее правило, если данное правило «сработало». Можно пропускать несколько правил, если указать их количество, например: «S=3».
  • E (env) устанавливает переменную окружения, например: «E=переменная:значение».

Примеры (во всех случаях показано содержимое файла .htaccess, расположенного в корневом каталоге веб-сайта):

# Пример 1. Каталоги проектов project1 и project2 веб-сайта www.site.com ранее содержали статические 
# html-страницы, теперь же эти страницы расположены на двух отдельных веб-сайтах project1.ru и project2.ru 
# (в той же иерархии)
 
# Первый способ требует наличия модуля mod_proxy и создает дополнительную нагрузку на веб-сервер, но зато 
# посетитель веб-сайта не знает, откуда в действительности выбираются веб-страницы
 
# Символы / даются с вопросительными знаками, чтобы правильно обработать ссылки вида
# http://www.site.com/project1 и http://www.site.com/project1/
 
RewriteRule ^project1/?(.*) http://project1.ru/$1 [P]
RewriteRule ^project2/?(.*) http://project2.ru/$1 [P]
 
# Второй способ возвращает внешние редиректы, так что посетитель увидит в адресной строке своего браузера, 
# что страницы реально расположены на других веб-сайтах
 
RewriteRule ^project1/?(.*) http://project1.ru/$1 [R]
RewriteRule ^project2/?(.*) http://project2.ru/$1 [R]
 
# Допустим, что в редиректах мы желаем передать в запросе какие-нибудь дополнительные параметры. 
# Применение флага QSA позволит нам сохранить параметры оригинального запроса, так что ссылка 
# http://site.com/project1/news.pl?mode=daily будет преобразована в
# http://project1.ru/news.pl?came_from=site.comamode=daily
 
RewriteRule ^project1/?(.*) http://project1.ru/$1?came_from=site.com [R,QSA]
RewriteRule ^project2/?(.*) http://project2.ru/$1?came_from=site.com [R,QSA]
# Пример 2. Электронная книга отдается динамическим скриптом в то время как нам желательно иметь 
# "красивую" иерархию вида "http://lib.ru/book1/chapter3.html". Кстати, расширение .html помогает нам скрывать 
# динамическую природу нашего веб-сайта
 
RewriteRule ^([a-z0-9]+)/([a-z0-9]+)\.html$ /cgi-bin/view_chapter.cgi?book=$1&amp;chapter=$2 [NC]
# Пример 3. Нам желательно скрыть от пользователя используемую на веб-сайте технологию, для чего мы не будем 
# пользоваться расширениями в наших http-ссылках. Без флага L данное правило зациклится
 
RewriteRule (.+) $1.html [L]
 
# В то же время посетитель может ввести ссылку с расширением по одному ему понятным причинам. Правильно 
# обработать такую ситуацию поможет следующее правило:
 
RewriteRule ^([^.]+) $1.html [L]
# Пример 4. На веб-сайте есть статические ссылки с расширением .html и динамические ссылки с расширением .pl. 
Допустим, что динамические ссылки остались прежними, а статические должны обрабатываться cgi-скриптом
# Первый вариант предельно прост:
 
RewriteRule (.+)\.html$ /cgi-bin/new_script.cgi?page=$1 [L]
 
# Второй вариант более общий. Например, если нам нужно преобразовать массу различных ссылок кроме одной-двух, 
# можно воспользоваться специальной "заменой без изменения" (обозначается символом -):
 
RewriteRule \.pl$ - [L]
RewriteRule (.*) /cgi-bin/new_script.cgi?page=$1 [L]
# Пример 5. Есть один особый случай, когда делается внешний редирект на относительную ссылку. Допустим, мы 
# находимся в каталоге /home/site.com/www/test веб-сайта site.com. Каталог доступен по ссылке http://site.com/test/. 
# Нам нужен внешний редирект с файлов *.html на *.shtml. Приводимые директивы записываются 
# в файл /home/site.com/www/test/.htaccess
 
# Решение тривиально, если использовать абсолютную замену, но в этом случае нам приходится жестко прописывать 
# название каталога, что не совсем хорошо:
 
RewriteRule (.+)\.html /test/$1.shtml [R]
 
# Если написать замену как относительную ссылку (см. ниже), то результат будет не таким, каким мы его ожидаем 
# увидеть (это обусловлено особенностями преобразования ссылок на уровне каталогов): например, ссылка 
# http://site.com/test/aaa.html будет преобразована в http://site.com/home/site.com/www/test/aaa.shtml
 
RewriteRule (.+)\.html $1.shtml [R]
 
# По полученной ссылке видно, что там подставлен полный реальный путь к нужному файлу. Решить проблему можно 
# при помощи директивы RewriteBase, параметром которой является префикс для всех относительных замен, 
# находящихся в данном файле .htaccess
 
RewriteBase /test
# Пример 6. Задание переменных окружения применяется очень редко, но тем не менее приведем два примера, 
# не нуждающихся в пояснении
 
# Сохраняет в окружении расширение исходного файла
 
RewriteRule ^([^.]+)\.([a-z]+)$ /cgi-bin/new_script.cgi?page=$1 [L,E=EXT:$2]
 
# Сохраняет в окружении содержимое http-заголовка X-Forwarded-For
 
RewriteRule \.(cgi|pl)$ - [L,E=%{HTTP:X-Forwarded-For}]

Несмотря на такое изобилие, преобразование ссылок не ограничивается только директивой RewriteRule. Есть еще одна директива, которая используется не менее часто — это директива RewriteCond. Данная директива предназначена для проверки некоторых дополнительных параметров и всегда ставится непосредственно перед директивой RewriteRule. Если директива RewriteCond «срабатывает», то проверяется следующая за ней директива RewriteRule, если же «не срабатывает», то директива RewriteRule игнорируется.

# Если подряд записаны несколько директив RewriteCond, то следующая за ними директива RewriteRule 
# проверяется только в том случае, когда "сработали" все директивы RewriteCond:
 
RewriteCond условие1
RewriteCond условие2
RewriteRule преобразование1
RewriteRule преобразование2
 
# Следует обратить внимание, что в приведенном выше примере вторая директива RewriteRule проверяется в любом 
# случае, так как все директивы RewriteCond относятся только к первой директиве RewriteRule. Если же вы желаете, 
# чтобы условия относились к обеим директивам RewriteRule, то вам придется повторить их еще раз:
 
RewriteCond условие1
RewriteCond условие2
RewriteRule преобразование1
RewriteCond условие1
RewriteCond условие2
RewriteRule преобразование2
 
# Применение флага OR позволяет объединять условия не по И (как это делается по умолчанию), а по ИЛИ. В 
# следующем примере директива RewriteRule проверяется, если выполняется любое из двух предшествующих условий:
 
RewriteCond условие1 [OR]
RewriteCond условие2
RewriteRule преобразование
 
Синтаксис директивы RewriteCond выглядит следующим образом:
 
RewriteCond «проверяемое выражение» «условие» «флаги»

Проверяемое выражение — это строка, которая может состоять из обычных символов, макросов и переменных. Макросы $1, $2 и так далее ссылаются на соответствующие выражения в скобках из следующей по порядку директивы RewriteRule. Макросы %1, %2 и так далее ссылаются на выражения в скобках из предыдущей по порядку директивы RewriteCond. Кстати, макросы %* могут также использоваться и в директивах RewriteRule для ссылки на предыдущую директиву RewriteCond.

Переменные записываются в виде %{ИМЯ_ПЕРЕМЕННОЙ}. Наиболее часто используются следующие переменные:

  • QUERY_STRING (параметры запроса),
  • REMOTE_ADDR (IP-адрес посетителя),
  • REMOTE_HOST (имя хоста посетителя),
  • REMOTE_USER (имя пользователя, если он прошел авторизацию),
  • REMOTE_METHOD (обычно GET или POST),
  • PATH_INFO (путь к файлу веб-страницы),
  • HTTP_USER_AGENT (содержимое http-заголовка User-Agent),
  • HTTP_REFERER (содержимое http-заголовка Referer),
  • HTTP_COOKIE (содержимое http-заголовка Cookie),
  • HTTP_HOST (имя хоста веб-сайта),
  • TIME_YEAR (все переменные TIME_* хранят разбитые на части текущие дату и время), TIME_MON, TIME_DAY, TIME_HOUR, TIME_MIN, TIME_SEC, TIME_WDAY,
  • REQUEST_URI (строка запроса без имени хоста и параметров запроса),
  • REQUEST_FILENAME (имя файла из REQUEST_URI),
  • THE_REQUEST (полная строка запроса в том виде, в котором ее присылает браузер посетителя).
  • Помимо стандартных переменных можно проверять содержимое любого http-заголовка: %{HTTP:Название-Заголовка}.

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

  • =ABC — значение переменной должно быть лексически равно строке ABC;
  • >ABC — значение переменной должно быть лексически больше строки ABC;
  • <ABC — значение переменной должно быть лексически меньше строки ABC;
  • -d — должен существовать каталог, имя которого совпадает со значением переменной;
  • -f — должен существовать файл, имя которого совпадает со значением переменной;
  • -s — должен существовать файл ненулевой длины, имя которого совпадает со значением переменной;
  • -l — должен существовать симлинк, имя которого совпадает со значением переменной;
  • -F— должен существовать файл, имя которого совпадает со значением переменной, и этот файл должен быть доступен по внешней ссылке на данный веб-сайт;
  • -U — должна быть доступна http-ссылка, имя которой совпадает со значением переменной.

Флагов может быть всего два: OR (объединение директив RewriteCond по ИЛИ, как было написано выше) и NC (отключение проверки регистра аналогично одноименному флагу для директивы RewriteRule).

И, наконец, примеры применения:

# Пример 1. Жесткий запрет посещений нашего веб-сайта для робота поисковой системы Google
 
RewriteCond %{USER_AGENT} Googlebot
RewriteRule .* - [F]
 
# Другой вариант возвращает вместо ошибки 403 (FORBIDDEN) ошибку 404 (NOT_FOUND)
 
RewriteCond %{USER_AGENT} Googlebot
RewriteRule .* - [R=404]
# Пример 2. Есть два каталога /home/site/storage1 и /home/site/storage2, в которых нужно искать запрашиваемые файлы
 
RewriteCond /home/site/storage1/%{REQUEST_FILENAME} -f
RewriteRule (.+) /home/site/storage1/$1 [L]
RewriteCond /home/site/storage2/%{REQUEST_FILENAME} -f
RewriteRule (.+) /home/site/storage2/$1 [L]
# Пример 3. Если ссылка не найдена на нашем веб-сайте, отправить посетителя на www.site.ru
 
RewriteCond %{REQUEST_URI} !-U
RewriteRule (.*) http://www.site.ru/$1 [R]
# Пример 4. Закрыть доступ к веб-сайту в рабочее время
 
RewriteCond %{TIME_HOUR}%{TIME_MIN} >1000
RewriteCond %{TIME_HOUR}%{TIME_MIN} <1900
RewriteRule .* - [F]
# Пример 5. Есть скрипт, раз в сутки производящий оптимизацию базы данных. Если посетитель зайдет в
 этот момент на веб-сайт, то получит ошибку - вместо этого необходимо показать ему страницу с сообщением о том, 
что через пару минут все придет в норму. Оптимизирующий скрипт на время своей работы создает файл /home/site/optimizer.pid
 
RewriteCond /home/site/optimizer.pid -f
RewriteRule .* /optimization_message.html
# Пример 6. Посетители веб-сайта авторизуются при помощи стандартной авторизации (AuthType BasicAuth).
# Необходимо по ссылке /home/* показывать содержимое их домашних каталогов
 
RewriteCond %{REMOTE_USER} !=""
RewriteCond /home/(%{REMOTE_USER}) -d
RewriteRule (.*) /home/%1/$1

И в заключение вкратце упомянем еще о двух директивах преобразования ссылок, которые не входят в модуль mod_rewrite — это Redirect и RedirectMatch. Ими можно пользоваться, во-первых, как упрощенными вариантами директивы RewriteRule, а во-вторых, в случаях, когда модуль mod_rewrite по каким-то причинам отсутствует в вашей сборке веб-сервера Apache. Примеры:

# Обе директивы при «срабатывании» возвращают редиректы. 
# В качестве замены всегда должна использоваться абсолютная ссылка
 
# Обычный безусловный редирект:
Redirect /news http://www.site.com/cgi-bin/news.cgi
 
# Редирект с подстановкой:
RedirectMatch (.*\.gif)$ http://www.site.com/alt/path/to/gif/files$1

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

By sysadmin on | FreeBSD, Linux
Метки: ,

Просмотр байтовых счетчиков трафика на интерфейсе во FreeBSD и Linux

По умолчанию «netstat -i» во FreeBSD показывает только число пакетов, чтобы посмотреть размер в байтах
нужно использовать опцию «-b», упоминание которой удалось найти после трех прочтений man страницы.

   netstat -inb

Для наглядного просмотра, можно использовать опцию «-h», которая сокращает байтовый вывод до Кб, Мб или Гб.

   netstat -inbh

Интенсивность передачи трафика удобно просматривать через:

   systat -ifstat

или

   netstat -iw1

Для просмотра интенсивности передачи трафика в Linux удобно использовать команду ifstat

В Linux байтовые счетчики интерфейсов можно просмотреть через:

   cat /proc/net/dev

Другую полезную статистику по работе сетевой подсистемы можно найти в файлах /proc/net/ip_conntrack, /proc/net/stat/rt_cache, и /proc/net/stat/arp_cache.

By sysadmin on | FreeBSD, Linux
Метки: , , ,

Оптимизация кэша squid

Все описанные здесь изменения делаются в файле squid.conf, который в большинстве дистрибутивов расположен в /etc/squid/

Сначала вспомним про очень полезную опцию: reload_into_ims. По умолчанию она выключена. Если ещё включить, то вместо reload squid будет посылать запрос If-Modified-Since. Это нарушение стандарта HTTP, однако большинство серверов корректно обрабатывают этот запрос, потому включаем:

reload_into_ims on

Далее находим параметр refresh_pattern. Он задаёт параметры кэширования. Стандартно шаблоны выглядят так:

refresh_pattern ^ftp:          1440    20%     10080
refresh_pattern ^gopher:       1440    0%      1440
refresh_pattern .              0       20%     4320

Обычно используется эта инструкция так:

refresh_pattern regex min percent max options

Опции означают следующее:

Опция Значение
regex Регулярное выражение. Описывает адреса, к которым применимо это правило.
min Минимальное время, в течении которого объект в кэше считается новым. Рекомендуется использовать 0, чтобы корректно отображались динамические страницы.
percent Процент от возраста объекта с явным указание срока актуальности, в течении которого объект считается новым.
max Указывает верхний предел времени, в течении которого объекты без явного указания времени актуальности считаются новыми.
options Дополнительные опции, перечисляемые через пробел. Самые интересные из них:

  • override-expire: заставляет игнорировать факт истечения времени актуальности объекта.
  • override-lastmod: заставляет игнорировать переданное сервером время последней модификации объекта.
  • ignore-reload: заставляет игнорировать запрос reload от клиента и выдавать версию объекта из кэша.
  • ignore-no-cache: заставляет игнорировать заголовок no-cache с сервера и принудительно кэшировать объект.

Правила обрабатываются сверху вниз до первого сработавшего правила. Потому правило для «.» должно идти последним.

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

#refresh_pattern ^ftp:          1440    20%     10080
#refresh_pattern ^gopher:       1440    0%      1440
#refresh_pattern .              0       20%     4320

Далее настроим более жёсткое кэширование для определённых типов файлов:

refresh_pattern \.bz2$          43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern \.exe$          43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern \.gif$          43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern \.gz$           43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern \.ico$          43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern \.jpg$          43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern \.mid$          43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern \.mp3$          43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern \.pdf$          43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern \.swf$          43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern \.tar$          43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern \.tgz$          43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern \.zip$          43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache

Уже это даёт солидную экономию. Далее на очереди реклама. Конечно её можно вырезать с помощью bfilter и/или adzapper, но ни один фильтр не может убрать всей рекламы, потому на всякий случай добавим правила для кэширования рекламы:

refresh_pattern http://ad\.                        43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern http://ads\.                       43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern http://adv\.                       43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern http://click\.                     43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern http://count\.                     43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern http://counter\.                   43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern http://engine\.                    43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern http://img\.readme\.ru             43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern http://userpic\.livejournal\.com   43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern \.ru/bf-analyze                    43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern \.ru/bf-si                         43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern /advs/                             43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern /banners/                          43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache
refresh_pattern /cgi-bin/iframe/                   43200   100%    43200 override-lastmod override-expire ignore-reload ignore-no-cache

Далее полезно ещё раз изучить логи squid. Возможно вы напишите какие-то свои дополнительные правила.

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

refresh_pattern ^ftp:           1440    20%     10080
refresh_pattern ^gopher:        1440    0%      1440
refresh_pattern .               0       80%     14400

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

За размер кэша отвечает параметр cache_dir:

# cache_dir ufs /var/spool/squid 100 16 256
cache_dir ufs /var/spool/squid 10240 16 256

За максимальный размер объекта в кэше отвечает параметр maximum_object_size:

# maximum_object_size 4096 KB
maximum_object_size 10240 KB

Закончив изменения сохраняем файл и даём команду squid перечитать настройки:

squid -k reconfigure

На этом всё. Если вы используете sarg для анализа логов squid то вы наверняка заметите рост эффективности кэша. (У автора использование кэша увеличилось с 6% до 28%)

By sysadmin on 20.02.2009 | FreeBSD, Linux
Метки: , , ,

Решение проблем, возникающих при выполнении команд ./configure, make и make install

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

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

Мы можем разделить ошибки на три категории:

  • Ошибки при выполнении команды ./configure
  • Ошибки при выполнении команды make
  • Ошибки при выполнении команды make install

Очевидно, что ошибки при выполнении команды ./configure, возникают во время выполнения скрипта конфигурации, ошибки при выполнении команды make возникают во время выполнения команды make, а ошибки при выполнении команды make install, соответственно, возникают при выполнении команды make install. Далее будет представлен лист типичных ошибок и способ их решения, разделенный на эти три категории.

Ошибки при выполнении команды ./configure

Следующий список содержит некоторые общие ошибки, которые может выдать каманда ./configure. Ошибки отсортированы по частоте возникновения. Сначала наиболее часто встречающиеся. Вещи между ( и ) являются опциональными, они могут не появлятся. OR, выделенное жирным курсивом означает, что несколько ошибок имеют одно решение. Текст между < и > показывает тип строки, которая должна появиться в этом месте.

1. (configure:) (error:) <somename> (&ltsomeversion> (or higher)) not found. (Please check your installation!) OR checking for <somename>… (configure:) (error:) not found. OR (configure:) (error:) <somename> (<someversion> (or newer)) is required to build <package-you’re-trying-to-compile>

  • Это обычно означает что -dev или -devel версия пакета ,который называется <somename> не установлена у вас на компьютере. Используйте менеджер пакетов вашего дистрибутива (или любой другой способ найти и установить пакет), чтобы найти пакет <somename> и установить его, если это возможно, -dev или -devel версию. Если -dev или -devel версия уже установлена, или её не сущечтвует, посмотрете на версию уже установленной. Она достаточно новая? Если она ниже, чем <someversion>, попробуйте обновить пакет. Если обновить пакет не представляется возможным, вы можете попробовать скомпилировать более мтарую версию программы. Более старые версии обычно используют более старые версии библиотек и программ, необходимых для компиляции.

2. (configure:) (error:) cannot find header (file) <somename>.h OR (configure:) (error:) (header) (file) <somename>.h missing! OR <similar>

  • Конфигурационный скрипт не может найти .h файл, необходимый для компиляции. Эта ошибка похожа на предыдущую, в которой необходимо установить -dev или -devel версию пакета. Однако, обычно не понятно какой пакет нужно установить для решения этой проблемы, так как <somename> может быть очень общим названием. Попробуйте поискать в интернетет <somename>.h, чтобы узнать в каком пакете этот файл находится, а затем установите этот пакет (и его -dev или -devel версия, если это возможно) с помощью менеджера пакетов вашего дистрибутива.

3. (configure:) (error:) no acceptable cc found in <somedirectories>

  • Вы используете для установки компилятор gcc, А переменная окружения CC отсутствует или не установлена. Убедитесь, что пакет gcc установлен, используя менеджер пакетов вашего дистрибутива. Если этот пакет не установлен, установите его. Если он установлен, попробуйте выполнить следующую команду:
[rechosen@localhost ~]$ export CC="/usr/bin/cc"

Если это помогло, вы можете добавить эту команду в /etc/profile (это файл, содержащий команды, которые выполняются когда пользователь входит в систему) и тогда вам не придется набирать её снова.

4. (configure:) (error:) C++ preprocessor «/lib/cpp» fails sanity check

  • Ваш пакет g++ отсутствует или поврежден. Используйте Используйте менеджер пакетов вашего дистрибутива (или любой другой способ найти и установить пакет), чтобы найти пакет g++ и установить его. Не забудьте, что в некоторых дистрибутивах этот пакет называется не g++. Fedora, например, использует название gcc-c++ в соем репозитарии yum. Если вы не можете найти g++, попробуйте поискать c++, cpp или gcc.

5. (configure:) (error:) C++ preprocessor «CC (-E)» fails sanity check

  • Эта ошибка вызвана странным «багом» в некоторых версиях библиотеки libtool, которая заставляет конфигурационный скрипт проверять все компиляторы поддерживающиеся libtool. Наиболее простое решение — установить g++.


Ошибки при выполнении команды make

Так как ошибки при выполнении команды make обычно очень специфичны, я дам список основных вещей, которые могут помочь:

  • Если вы компилируете программу с использованием gcc 4 (используйте gcc -dumpversion чтобы это выяснить), попробуйте использовать более старые версии компилятора. Сначала убедитесь, что у вас установлена более старая версия. Обычно это можно узнать, использовав следующую команду:
    [rechosen@localhost ~]$ ls /usr/bin/gcc*

    Если она вернет что-то вроде этого:

    /usr/bin/gcc /usr/bin/gcc32

    То можете использовать команды gcc32, чтобы скомпилировать программу в более ранними версиями gcc. Если команда не вернет подобной строки, то используя менеджер пакетов вашего дистрибутива, найдите и установите более ранние версии gcc (обычно они называются compat-gcc или gcc-<versionnumber>). После установки, вам должна быть доступна альтернативная версия gcc. Её можно найти используя команду ls. Заставить команды ./configure, make и make install использовать более старую версию gcc можно так:

    [rechosen@localhost ~]$ CC="/usr/bin/gcc32" ./configure
    [rechosen@localhost ~]$ CC="/usr/bin/gcc32" make
    [rechosen@localhost ~]$ CC="/usr/bin/gcc32" make install

    Конечно путь /usr/bin/gcc32 надо заменить на тот, по которому у вас находится альтернативная версия gcc.

  • Иногда ошибки могут вызваны простым «багом» программы. Попробуйте скачать последнюю версию программы (используя её cvs, svn или другой репозитарий, или скачав последний снимок) и скомпилируйте её, возможно эта ошибка уже исправлена.
  • Ошибка при выполнении комадны make может быть также вызвана неправильной версией необходимой библиотеки или программы. Эта проблема часто встречается для очень новых или очень старых пакетов. Проверьте зависимости пакета (они обчно написаны на сайте программы) и сравните номера версий с версиями, установленными у вас на компьютере (их обчно можно посмотреть, используя менеджер пакетов вашего дистрибутива). Если номер версии в вашей системе больше того, которые написан на сайте, возможно вы пытаетесь скомпилировать очень старый пакет. Если вам дейсвительно необходимо его скомпилировать, попробуйте установить более старые версии зависимых пакетов.Как бы то небыло, обычно лучше поискать другой способ установки этого пакета или поискать альтернативу. Если номер версии в системе меньше, чем на сайте, вы можете попробовать обновить соответствующий пакет.Вы можетепопробовать обновить требуемую библиотеку или скомпилировать более старую весию программы.Так же проверьте, может уже есть этот пакет, скомпилированный для авшего дистрибутива. Его установка, обычно, проще, чем исправление ошибок компиляции.
  • Другая вещь, которую стоит попробовать — это поиск специфической ошибки в интернете. Если вы не нашли ничего полезного, попробуйте убрать такие вещи, как номер строки (он может измениться с новой версией), номер версии (его можно заменить звездочкой, если он содержится в названии программы) и специальные символы, такие как кавычки, так как они влияют на поисковый сервис. Обычно можно найти много информации в листе рассылок. Иногда выходит патч, который исправляет ошибки в исходном коде. Его можно применить слудеющим образом:
    [rechosen@localhost ~]$ patch -Np1 <patchfile>

    Не забудьте: чтобы применить патч, текущей должна быть директория с исходными текстами.


Ошибки при выполнении команды make install

Эти ошибки обычно легко понять, но я все равно про них напишу. Есть два наиболее частых случая, почему команда make install возвращает ошибку:

  • У вас нет прав пользователя root. Попробуйте выполнить команду make install, используя команду sudo, или станеть пользователем root, используя команду su. Команда sudo применяется следующим образом:
    [rechosen@localhost ~]$ sudo make install

    Она спросит пароль; обычно используется собственный пароль или пароль пользователя root. Вы можете испльзовать команду su, чтобы стать польpователем root:

    [rechosen@localhost ~]$ su

    Эта команда тоже спросит пароль, но в данном случае наобходим именно пароль пользователя root. После того, как вы стали пользователем root, просто выполните команду make install.

  • Пакет, который вы только что скомпилировали не имеет команды установки. В этом случае вам надо скопировать скомпилированный бинарный файл в директорию bin вручную. Если вы выполните команду ls в директории исходного кода, исполняемый файл должен быть светло зеленого цвета. Его надо скопировать в /usr/bin (или, если хотите, в /usr/local/bin) следующей командой:
    [rechosen@localhost ~]$ cp <executablefile> /usr/bin

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


Другие проблемы

Вот список некоторых других возможных проблем и их решения:

  • Все проходит хорошо, но когда я набираю имя программы, которую только что установил, bash говорить, что не может её найти. Это обычно происходит из-за того, что make install устанавливает все в /usr/local или in /opt/<packagename>. Посмотрите на вывод команды make install: куда скопированы файлы? Попробуйте добвавить эту директорию в переменную PATH (следующий пример приведен для пакета, установленного в /usr/local):
    [rechosen@localhost ~]$ export PATH="$PATH:/usr/local/bin"

    Вам надо заменить /usr/local/bin на директорию, в которой установлены исполняемые файлы вашего пакета. Если это помогло, добавьте эту строку в /etc/profile, чтобы вам не пришлось набирать её каждый раз. Кстати, вы можете контролировать место, куда установится пакет, указав следующую опцию, когда запускаете конфигурационный скрипт:

    [rechosen@localhost ~]$ ./configure --prefix=/usr

    Измените /usr на директорию, в которую хотите установить пакет. Не забудьте, что вы устанавливаете только префикс; бинарные файлы установятся в свою поддиректорию, библиотеки в свою, заголовочные файлы в свою и т.д. Например при использовании указанного префикса, бинарные файлы будут установлены в /usr/bin.

  • Я хочу установить очень старую версию пакета, но я не могу найти исходный код в интернете. У вас еще остается маленький шанс. Попробуйте найти rpm файл пакета той версии, которую вы хотите и скачайте соответствующий src rpm файл. Распаковать его можно следующим образом:
    [rechosen@localhost ~]$ rpm2cpio <pmfile> | cpio -idv

    Теперь можно использовать исходный код, извлеченный из rpm файла.

By sysadmin on | FreeBSD, Linux
Метки: , , , , , ,

Использование комманд diff и patch

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

В этой статье используются без объяснения некоторые базовые команды Linux, такие как смена смена директории, копирование файлов и редактирование текстовых файлов.

Использование diff для создания простого патча

Наиболее простой пример использования команды diff — получение различий между двумя файлами, оригинальным и обновленным. Можете, например, написать насколько слов обычного текста, сделать какие-нибудь изменения, и сохранить измененния во второй файл. Теперь вы можете сравнить эти эти два файла, используя команду diff:

[rechosen@localhost ~]$ diff originalfile updatedfile

Конечно, надо заменить originalfile и updatedfile соответствующими именами файлов. В результате должно получиться что-то вроде этого:

1c1
 
< These are a few words.
 
\ No newline at end of file
 
---
 
> These still are just a few words.
 
\ No newline at end of file

Обратите внимание: Что бы продемонстрировать создание простого патча, я использовал оригинальный файл, содержащий строку «These are a few words.», и измененный файл, содержащий строку «These still are just a few words.» Вы можете создать эти файлы сами, если хотите запустить команду из статьи и получить тот же результат.

1c1 показывает номер строки и то, что с ней надо сделать. Обратите внимание, что может быть сразу несколько строк(например, 12,15, что означает со строки 12 до строки 15). Символ «c» означает, что патч заменит эту строку. Есть еще два других символа: «a» и «d». Они означают «добавить»(add) и «удалить»(delete) соответственно. Таким образом, синтаксис следующий: (номер строки или диапазон строк)(c,a или d)(номер строки или диапазон строк), хотя когда используются «a» или «d», одна из частей (номер строки или диапазон строк) может содержать только номер одной строки.

  • Когда используется «c», номера строк слева — это строки в оригинальном файле, которые надо заменить строками, находящимися в патче, а номера строк справа — это строки, которые должны быть в пропатченном файле.
  • Когда используется «a», номер слева может быть только номером одной строки, который показывает, где надо добавить строку в пропатченном файле, а номера строк справа — это строки, которые должны быть в пропатченном файле.
  • Когда используется «d», номера строк слева — это строки, которые надо удалить, чтобы получить пропатченную версию файла, а номер строки справа может быть только номером одной строки, который показывает где будут строки в пропатченном файле, если они не будут удалены. Вы можете подумать, что последний номер не нужен, но не забывайте, что патч можно применить для восстаноления исходного файла. Это будет объяснено позже.

Знак «<» означает, что патч должен удалить символы после этого знака, а знак «>» означает, что символы после этого знака надо добавить. Когда надо заменить строки («c» между номерами строк), вы увидите оба знака: и «<«, и «>». Когда надо добавить строку («a» между номерами строк), вы увидите только знак «>», а когда надо удалить строку («d» между номерами строк), вы увидите только знак «<«.

Строка «\ No newline at end of file» появилась из-за того, что я не не нажал enter после того как набрал слова. Считается хорошим тоном заканчивать текстовый файл пустой строкой. Некоторым программам она необходима для работы. Поэтому эта строка появилась после работы команды diff. Добавим пустые строки в конец файлов, и получим более короткий вывод команды diff:

1c1
 
< These are a few words.
 
---
 
> These still are just a few words.

Как вы возможно заметили, я не объяснил что означают 3 знака «-«. Они означают конец строк, которые надо заменить и начало строк на которые надо заменить. Разделение старых и новых строк. Вы увидите это знак только при замене («c» между номерами строк).

Если мы хотим создать патч, мы должны поместить вывод команды diff в файл. Конечно это можно сделать, скопировав его из консоли и вставив в вашем любимом текстовом редакторе, а затем сохранив этот файл, но есть способ проще. Мы можем с помощью bash направить вывод команды diff в текстовый файл:

[rechosen@localhost ~]$ diff originalfile updatedfile > patchfile.patch

Опять же не забудьте заменить originalfile и updatedfile на соответствующие имена файлов. Вы наверное знаете, что опция bash «>» работает со всеми командами. Это очень полезное свойство.

Применение простого патча, который мы создали

Мы можем использовать патч, который только что создали, чтобы получить из оригинального файла обновленный. Для этого надо скопировать оригинальный файл и патч в одно и тоже место. И затем применить патч:

[rechosen@localhost ~]$ patch originalfile -i patchfile.patch -o updatedfile

Естественно, и здесь надо изменить имена файлов на необходимые. Если все прошло хорошо, должен получиться файл, идентичный обновленному. Вы можете убедиться в этом, используя команду diff с опцией «-s»:

[rechosen@localhost ~]$ diff -s updatedfile [/path/to/the/original/updatedfile]/updatefile

Замените текст между [ и ] на путь к оригинальному файлу. Например, если обновленный файл, который вы использовали при создании патча находится в родительской директории вышай текущей, то «[/path/to/the/original/updatedfile]» надо заменить на «..» (bash понимает это как родительскую директорию от текущей). И конечно надо изменить имена файлов на верные.

Поздравляю! Если diff сообщила, что файлы идентичные, вы только что успешно создали и применили патч! Однако формат патча, который мы только что использовали не единственный. В следующей главе мы рассмотрим другой формат патча.

Контекстный патч

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

[rechosen@localhost ~]$ diff -c originalfile updatedfile

Результат получится следующий:

*** originalfile        2007-02-03 22:15:48.000000000 0100
 
--- updatedfile 2007-02-03 22:15:56.000000000 0100
 
***************
 
*** 1 ****
 
! These are a few words.
 
--- 1 ----
 
! These still are just a few words.

Как вы видите, здесь включено имя файла. Это значит, что нам не придется набирать его во время применения патча. Далее идет дата и время последнего изменения файла. строка с 15 «*» показывает начало изменений. Они показывают, что надо сделать со следующим блоком текста. Два номера 1 — это номера строк (здесь тоже может быть сразу несколько строк), а «!» означает, что строки надо заменить. Строка с «!» перед тремя «-» должна быть заменена второй строкой с «!», которая идет после трех «-«(конечно сам ! не будет включен; это синтаксис контекстного формата). Как вы можете видеть, здесь нет знаков «c», «a» и «d».Действие, которое нужно сделать, определяется символом в начале строки. «!» означает замену. Другие символы — «+», «-» и » » (пробел). «+» означает добавление, «-» означает удаление, а » » означает ничего не делать: патч использует его чтобы убедиться, что он изменяет правильную часть файла.

Применять этот патч легче: при тех же условиях, что и для предыдущего патча (записываем вывод команды diff в файл, затем копируем патч и оригинал в одно и то же место), надо выполнить следующую команду:

[rechosen@localhost ~]$ patch -i patchfile.patch -o updatedfile

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

Получение различий между несколькими файлами

Наиболее простой способ получить различия между несколькими файлами — это положить их в одну директорию и выполнить команду diff для этой директории целиком. Вы можете просто передать команде diff в качестве параметров имена директорий вместо имен файлов:

[rechosen@localhost ~]$ diff originaldirectory/ updateddirectory/

Обратите внимание: Если в директория есть поддиректории, то надо использовать опцию «-r».

В результате должно получится что-то вроде этого:

diff originaldirectory/file1 updateddirectory/file1
 
1c1
 
< This is the first original file.
 
---
 
> This is the first updated file.
 
diff originaldirectory/file2 updateddirectory/file2
 
1c1
 
< This is the second original file.
 
---
 
> This is the second updated file.
 
14d13
 
< We're going to add something in this file and to delete this line.
 
26a26
 
> This is line has been added to this updated file.

Обратите внимание: Я создал несколько несколько файлов для примера. Вы можете скачать архив, содержащий эти файлы: http://www.linuxtutorialblog.com/resource/uploads/diffpatchexamplefiles.tar.gz.

Как вы видите, нормальный формат содержит только имена файлов и изменяемые строки.

Теперь используем контекстный формат:

diff -c originaldirectory/file1 updateddirectory/file1
 
*** originaldirectory/file1     2007-02-04 16:17:57.000000000 +0100
 
--- updateddirectory/file1      2007-02-04 16:18:33.000000000 +0100
 
***************
 
*** 1 ****
 
! This is the first original file.
 
--- 1 ----
 
! This is the first updated file.
 
diff -c originaldirectory/file2 updateddirectory/file2
 
*** originaldirectory/file2     2007-02-04 16:19:37.000000000 +0100
 
--- updateddirectory/file2      2007-02-04 16:20:08.000000000 +0100
 
***************
 
*** 1,4 ****
 
! This is the second original file.
 
  S
 
  O
 
--- 1,4 ----
 
! This is the second updated file.
 
  S
 
  O
 
***************
 
*** 11,17 ****
 
  C
 
  E
 
- We're going to add something in this file and to delete this line.
 
  S
 
  O
 
--- 11,16 ----
 
***************
 
*** 24,28 ****
 
--- 23,28 ----
 
  C
 
  E
 
+ This is line has been added to this updated file.
 
  Something will be added above this line.

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

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

Создать патч было легко, но использование директорий ставит следующую проблему: бедут ли патч изменять только соответствующие файлы в текущей директории, или будет использовать соответствующий путь, указанный в файле? Чтобы узнать это, смотрите следующую главу!

Применение патча к нескольким файлам

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

[rechosen@localhost ~]$ diff -c originaldirectory/ updateddirectory/ > patchfile.patch

Обратите внимание: мы используем контекстный формат патча, так как это является хорошим тоном.

Теперь надо использовать полученный патч. Скопируйте оригинальную директорию и патч куда-нибудь и примените следующую команду:

[rechosen@localhost ~]$ patch -i patchfile.patch

Однако возникает ошибка, что невозможно найти файлы для патча. Команда пытается найти файл file1 в текущей директории (по умолчанию патч убирает все пути перед именем файла). И конено файла нет, так как мы пытаемся обновить файлы в директории originaldirectory. Поэтому мы должны заставить патч использовать полный путь. Это делается следующим образом:

[rechosen@localhost ~]$ patch -p0 -i patchfile.patch

Обратите внимание: Вы может подумать, что можно просто переместиться в originaldirectory и запустить патч. Но это не так! Так делать не стоит: если в в патче содержатся поддиректории, то он будет искать их в рабочей директории, и не найдет, или найдет не те. Используйте опцию «-p», чтобы заставить патч искать файлы в поддиректориях.

Опция «-p» говорит патчу сколько слэшей (включая то, что перед ними, обычно директории) нужно вырезать перед именем файла (обратите внимание, что при использовании опции «-p0», патч будет будет искать файлы и в originaldirectory и в updateddirectory).Когда мы устанавливаем 0, это означает что не надо удалять пути, но можно поставить 1, чтобы удалить первый слэш, или 2, чтобы удалить два слэша, и т.д. Это может быть полезно, если если в патче используется структура каталогов, отличная от вашей. Например, если в патче используется следующая структура каталогов:

(...)
 
*** /home/username/sources/program/originaldirectory/file1     2007-02-04 16:17:57.000000000 +0100
 
--- /home/username/sources/program/updateddirectory/file1      2007-02-04 16:18:33.000000000 +0100
 
(...)

Вам надо просто посчитать количество слэшей (/ (1) home/ (2) username/ (3) sources/ (4) program/ (5)) и передать это число в опцие «-p». Если вы используете «-p5», то патч будет искать и в originaldirectory/file1 и в updateddirectory/file1. Не забудьте, что патч рассматривает два слэша друг за другом (как в /home/username//sources) как один. Это вызвано тем, что иногда патч скрипты добавляют дополнительный слэш между директориями.

Восстановление оригинального файла из пропатченного

Иногда возникает необходимость восстановить оригинальный файл из пропатченного. Например, если в нем содержится ошибка. Для этого надо использовать опцию «-R»:

[rechosen@localhost ~]$ patch -p0 -R -i patchfile.patch

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

Унифицированный формат

Есть еще один формат вывода различий командой diff: унифицированный формат. Он более компактен, так как содержит уменьшенные контекстные строки. Однако он поддерживается только GNU diff и patch. Если вы его используете, вы должны быть уверены, что у пользователей, для которых патч предназначен, GNU patch. Linux допускает использование этого формата.

Унифицированный формат похож на контекстный, но это не одно и тоже. Патч в унифицированном формате можно создать так:

[rechosen@localhost ~]$ diff -u originaldirectory/ updateddirectory/

Результат будет седующий:

diff -u originaldirectory/file1 updateddirectory/file1
 
--- originaldirectory/file1     2007-02-04 16:17:57.000000000 +0100
 
+++ updateddirectory/file1      2007-02-04 16:18:33.000000000 +0100
 
@@ -1 +1 @@
 
-This is the first original file.
 
+This is the first updated file.
 
diff -u originaldirectory/file2 updateddirectory/file2
 
--- originaldirectory/file2     2007-02-04 16:19:37.000000000 +0100
 
+++ updateddirectory/file2      2007-02-04 16:20:08.000000000 +0100
 
@@ -1,4 +1,4 @@
 
-This is the second original file.
 
+This is the second updated file.
 
 S
 
 O
 
@@ -11,7 +11,6 @@
 
 C
 
 E
 
-We're going to add something in this file and to delete this line.
 
 S
 
 O
 
@@ -24,5 +23,6 @@
 
 C
 
 E
 
+This is line has been added to this updated file.
 
 Something will be added above this line.

Как вы видите, номера строк заключены между «@». Кроме того, есть дополнительный пробел после «+» или «-«. Это экономит несколько байт. Другое различие: в унифицированном формате нет специального знака для замены. Он просто удаляет старые строки («-«) и добавляет новые («+»). Разница между этими действиями заключается в том, что при замене используется один и тот же номер строки, а при удалении и добавлении разные.

Сравнение форматов

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

  • Нормальный формат наиболее совместимый. Любые команды похожие на diff/patch должны понять его. Его недостаток — это отсутствие контекста.
  • Контекстный формат широко распространен, но не все команды его понимают. Его преимущество в наличии контекста.
  • Унифицированный формат тоже включает контекст, и при этом более компактем. Но его поддерживает только GNU diff and patch.

Если вы уверены, что патч буду использовать только пользователи с GNU diff/patch, то лучше всего выбрать унифицированный формат, так как он более компактный. В большинстве других случаев лучший выбор — это контекстный формат. Нормальный формат следует использовать если вы уверены, что пользователь будет применять патч командами, не поддерживающими контекстный формат.

Изменение количества контекстных строк

Можно заставить команду diff включать в патч сеньшее количество строк контекста, чем должно быть. В больших патчах это может сильон уменьшить его размер. Однако если уменьшить количество контекстных строк, это может привести в неработоспособности патча. Цитати из справки GNU diff: «Для большинства операций в патче должно быть хотя бы две строки контекста.»

Указать количество контестных строк можно несколькими способами:

  • Если вы хотит использовать контекстный формат, вы можете вы можете совместить эти указания, добавив в опцию «-C». Пример:
    [rechosen@localhost ~]$ diff -C 2 originaldirectory/ updateddirectory/

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

  • Если вы хотит использовать контекстный формат, вы можете вы можете совместить эти указания, добавив в опцию «-U». Пример:

    [rechosen@localhost ~]$ diff -U 2 originaldirectory/ updateddirectory/

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

  • Если не указывать какой формат вы хотите использовать, то команда будет выглядеть примерно так:
    [rechosen@localhost ~]$ diff -2 originaldirectory/ updateddirectory/

    Однако это будет работать только если вы определите формат. Вам необходимо использовать эту опцию или с «-c» или с «u».

Заключительные слова

Несмотря на то, что эта статья описывает множество особенностей работы команд diff и patch, она не может описать все их возможности. Если вы хотите узнать больше об этих командах, вы можете прочитать страницу помощи по этим командам и документацию GNU.

By sysadmin on 19.02.2009 | FreeBSD, Linux
Метки: , , ,

Прозрачный MC

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

К слову, пользователи KDE могут сделать это штатными следствами – в настройках Konsole, а для пользователей других WM такой способ просто недоступен.

Немного «погуглив», я нашел решение. В любом эдиторе (только не том, что входит в MC), например nano открываем файл ~/.mc/ini (в консоли это выглядит так: nano -w ~/.mc/ini). Идем в самый конец файла и дописываем там следующюю секцию:

[Colors]
base_color=normal=,default:selected=,:marked=,default:markselect=,:menu=,:menuhot=,:menusel=,:menuhotsel=,:dnormal=,:dfocus=,:dhotnormal=,:dhotfocus=,:input=,:reverse=,:executable=,default:directory=,default:link=,default:device=,default:special=,:core=,:helpnormal=,:helplink=,:helpslink=,:

Сохраняем изменения, закрываем, набираем mc и наслаждаемся видом «крутого» MC.

Очень полезное дополнение – MC будет прозрачным только под обычным юзером, от имени которого вы сделали эти изменения, если вы наберете su -c mc, то MC останется непрозрачным (в отличие от «прозрачности для МС» в KDE).

Очень удобно.

By sysadmin on | FreeBSD, Linux
Метки: , , ,

Пошаговая настройка SSL для Apache

Перевод статьи «Step by Step: Configuring SSL Under Apache» автора Juliet Kemp.

Вступление

Если у вас безопасный веб-сервер, пользователи, волнующиеся за безопасность своих данных, могут быть уверены, что запросы зашифрованы, поэтому их данные в безопасности. Лучшим путем для этого является использование Apache 2, лидирующего веб-сервера под Linux и Secure Sockets Layer, протокол безопасной передачи данных. Transport Layer Security (TLS) является развитием SSL, но они работают практически одинаково. Я буду ссылаться только на SSL.

SSL — протокол для безопасной передачи зашифрованных данных между веб-браузером и веб-сервером. В большинстве случаев, аутентификацию проходит сервер, что позволяет клиенту быть уверенным в том, что сервер является требуемым ему, а не наоборот. Как бы то ни было, когда соединение устанавливается, обе стороны находятся в безопасности, так как только клиент и сервер имеют доступ к ключу. Это работает в течении многих запросов, сервер не интересует, кем является клиент так долго, сколько он остается тем же клиентом на протяжении запроса. Если вас волнует аутентификация клиента, есть возможность использовать клиентские SSL сертификаты (или htaccess, Kerberos или другие, близкие к ним методы), но это не будет рассматриваться в этой статье.

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

Протокол SSL работает следующим образом:

1. Клиент подключается к веб-серверу и дает список доступных кодов.

2. Сервер берет наиболее устойчивый код, который поддерживает и он, и клиент, и посылает сертификат со своим именем и ключ кодирования, подписанный доверенным Удостоверяющим Центром (Certificate Authority, далее — CA), таким как Verisign.

3. Клиент проверяет сертификат с помощью CA. На практике, хранят набор CA локально, поэтому это может быть сделано без контакта в реальном времени с CA, и поэтому более быстро.

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

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

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

Настройка Apache для работы с SSL проста, но есть несколько необходимых шагов. Эта статья рассказывает, как получить сертификат, подписанный CA и как скомпилировать и настроить Apache для работы с SSL. Я использую Apache 2 с mod_ssl. ApacheSSL (реализация Apache с возможностями SSL) также доступен, но сейчас он уже устарел; mod_ssl намного лучше.

Создание сертификата.

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

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

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

openssl req -new -x509 -days 365 -sha1 -newkey rsa:1024 \
 
-nodes -keyout server.key -out server.crt \
 
-subj '/O=Company/OU=Department/CN=www.example.com'

Давайте рассмотрим опции более подробно:

— -x509 означает, что сертификат обязателен, правильнее, чем просто запрос сертификата (смотри ниже)

— -days 365 устанавливает время истечения сертификата, равное году. Вы можете увеличить этот срок. Запомните дату истечения срока, чтобы обновить её при необходимости.

— -sha1 указывает, что будет использован SHA1 для шифрования.

— rsa:1024 делает ключ 1024 битным RSA.

— -nodes указывает отсутствие пароля.

— -keyout и -out указывают, где хранить сертификат и ключ. Ключ должен быть доступен для чтения только для root; сертификат может быть доступен для чтения для world, но должен быть доступным для чтения пользователю, который запускает Apache.

— -subj устанавливает имя компании, имя отделения компании и адрес веб-сайта. Если вы это пропустите, вас попросят это сделать. CN должен совпадать с адресом сайта, иначе сертификат не будет соответствовать, и пользователи будут получать предупреждение при подключении. Убедитесь, что вы не запрашиваете пароль.

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

Не смотря на это, безусловно, лучше использовать сертификат, подписанный доверенным Удостоверяющим Центром, таким как Verisign (который имеет наибольший охват рынка), или меньшей организацией. Большинство браузеров уже имеют набор предустановленных сертификатов, заверенных CA, которые верифицируют сертификат вашего веб-сервера при подключении клиента. Это уменьшает количество трудностей для конечного пользователя и удостоверяет законность вашего сайта.

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

openssl req -new -sha1 -newkey rsa:1024 -nodes \ 
 
-keyout server.key -out www.example.com.csr \ 
 
-subj '/O=Company/OU=Department/CN=www.example.com'

Этот пример работает так же, как и предыдущий, но на этот раз мы не используем опцию -x509. Выполнение этой команды приведет к генерации ключа и запроса сертификата, но не самого сертификата. Если вы ввели CN и так далее, вы не должны вводить адрес e-mail или пароль.

Ключ сервера (файл server.key, который, опять же, должен быть доступен для чтения только для root) остается на вашем веб-сервере; запрос (файл www.example.com.csr) отправляется в CA. Вы можете назвать файл запроса так, как вам вздумается, но назвав его по своему доменному имени, вы упростите задачу для CA.

Следующей стадией будет послать этот файл www.example.com.csr в CA, с вашей оплатой. Они должны вернуть его достаточно быстро, если вы предоставили всю требуемую информацию в вашем запросе. Выбранный вами CA объяснит их действия на своем сайте. Вам может понадобиться поменять формат файла на PEM, но, в случае Verisign, этого делать не придется.

Когда вы получите файл назад в PEM формате, переименуйте его в server.crt (это не является строгой необходимостью, но соответствует условиям Apache) и проверьте его:

    openssl verify -CAfile /path/to/trusted_ca.crt \
 
		-purpose sslserver server.crt

Затем проверьте, что результат выполнения этих двух команд одинаков, т.е., что сертификат соответствует приватному ключу:

    openssl x509 -noout -modulus -in server.pem | openssl sha1
 
    openssl rsa -noout -modulus -in server.key | openssl sha1

Теперь установите ваш ключ (сгенерированный выше как server.key) и сертификат (server.crt) в /etc/apache2/ssl или предпочитаемый вами каталог настроек, если он другой. Как указано выше, очень важно убедиться, что server.key доступен для чтения только для root, в то время как сертификат сервера может быть доступен для чтения для world, но принадлежать и быть доступным для записи только для root.

Компиляция Apache с SSL.

Итак, ваш сертификат сгенерирован. Теперь вам надо настроить свой сервер для его использования.

Для подавляющего большинства людей, лучшим способом установить и управлять Apache2 — модули, полученные через менеджер пакетов вашего дистрибутива. Apache2 из Debian идет вместе с модулем SSL, но он не включен по умолчанию. Для его включения вы должны выполнить команду: a2enmod ssl и перезапустить веб-сервер.

Чтобы сделать это, добавьте строчку

    Include /etc/apache2/mod_ssl.conf

в ваш /etc/apache2/apache2.conf (этот файл может также называться httpd.conf). Вы должны исправить её, обозначив соответствующее расположение файла mod_ssl.conf. Затем перезапустите веб-сервер.

Если вы хотите скомпилировать Apache2 из исходных кодов, в зависимости от того, какие установки вы до этого использовали, вы можете уже иметь или не иметь поддержку SSL. Проверьте это командой apache2 -l. Если перекомпиляция понадобится, запустите ./configure со всеми опциями, которые вы использовали до этого, добавив к ним —enable-ssl и —enable-setenvif (последняя нужна для совместимости с капризами Internet Explorer). Затем установите его как обычно, с помощью make;make install и проверьте правильность прав доступа.

Настройка Apache с SSL.

Следующим шагом будет настройка Apache2. Следующие инструкции приведут к запуску сервера как безопасного (порт 443) и как обычного веб-сервера (порт 80). Прежде всего, вам надо настроить сервер на принятие запросов на оба порта. Или отредактируйте /etc/apache2/ports.conf (в Debian, это входит в apache2.conf), или отредактируйте /etc/apache2/apache2.conf, включив строки:

Listen 80
 
Listen 443

Затем отредактируйте /etc/apache2/sites-enabled/yoursite для использования настроек SSL. Разделение настроек обычного и безопасного сервера с помощью VirtualHost — простейший способ из соображений условий эксплуатации. Любые настройки вне секций VirtualHost (например, установка ServerAdmin) будут применяться для обоих (и любых других) VirtualHost. Добавьте следующий текст в файл конфигурации:

# =================================================
 
# SSL/TLS settings
 
# =================================================
 
NameVirtualHost *:443
 
    DocumentRoot "/local/www/ssl_html"
 
    SSLEngine on
 
    SSLOptions +StrictRequire
 
        SSLRequireSSL
 
    SSLProtocol -all +TLSv1 +SSLv3
 
    SSLCipherSuite HIGH:MEDIUM:!aNULL:+SHA1:+MD5:+HIGH:+MEDIUM
 
    SSLRandomSeed startup file:/dev/urandom 1024
 
    SSLRandomSeed connect file:/dev/urandom 1024
 
    SSLSessionCache shm:/usr/local/apache2/logs/ssl_cache_shm
 
    SSLSessionCacheTimeout 600    
 
    SSLCertificateFile /etc/apache2/ssl/server.crt
 
    SSLCertificateKeyFile /etc/apache2/ssl/server.key
 
    SSLVerifyClient none
 
    SSLProxyEngine off
 
        AddType application/x-x509-ca-cert      .crt
 
        AddType application/x-pkcs7-crl         .crl
 
    SetEnvIf User-Agent ".*MSIE.*" \  
 
      nokeepalive ssl-unclean-shutdown \  
 
      downgrade-1.0 force-response-1.0

Несколько замечаний об этой конфигурации:

— SSLEngine должен быть включен, обозначая, что сервер использует SSL.

— DocumentRoot устанавливает корневой каталог виртуального хоста. Это значит, что вы можете отделять безопасное содержимое от обычного.

— SSLRequireSSL запрашивает использование SSL (на этом виртуальном сервере), то есть, пользователь не может подключиться к этому виртуальному хосту с помощью обычного HTTP-запроса. Вот зачем мы разделили безопасное и обычное содержимое.

— SSLProtocol отключает все протоколы, отличные от TLS v1.0 и SSL v3.0. Для современных браузеров все будет работать хорошо.

— SSLCipherSuite устанавливает использование только HIGH и MEDIUM шифров. SHA1 считается более безопасным, чем MD5, поэтому выбран он.

— SSLCertificateFile и SSLCertificateKeyFile указывают расположение файлов сертификата и ключа.

— SSLVerifyClient должна быть установлена как ‘none’, если не используется аутентификация примера.

Чтобы запускать обычный сервер на 80 порту, добавьте следующий текст в конфигурационный файл:

NameVirtualHost: *.80
 
    DocumentRoot "/local/www/html"

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

Тестирование.

Создайте базовую страницу index.html в корневой директории вашего сервера, если у вас ещё нет содержимого там.

Затем направьте свой браузер на https://yoursite.com. Вы должны увидеть открытие SSL-соединения и загрузку страницы. Если вы используете сертификат, подписанный вами, ваш браузер даст предупреждение о том, что подлинность сервера не может быть проверена. Вы можете выбрать просмотр сертификата и принять его. Если вы используете внешний сертификат, все должно пройти без проблем.

Убедитесь, что не можете получить доступ к безопасному содержимому, используя http://. Если вы попробуете, вы должны получить сообщение об ошибке.

Устранение проблем.

Если это работает не так, как ожидалось, прежде всего, проверьте, что ваш сервер вообще запущен с помощью команды ps -a | grep apache. Если она не вернет результата, попробуйте перезапустить сервер и проверьте сообщения об ошибке в консоли.

Также проверьте, что права доступа к файлам сертификата и ключа установлены правильно (см. выше), также, как и права к тестовому HTML-файлу и директории, в которой он находится.

Затем, проверьте логи. Вы должны проверить как логи сервера, так и логи SSL, которые вы настроили в конфигурационном файле выше. Если вы не нашли там ничего полезного, попробуйте поменять значение LogLevel в файле конфигурации Apache2 на ‘debug’, перезапустите Apache2 и протестируйте снова. Это должно дать больше данных в логах.

Если вы запускаете веб-сервер на 80 порту, попробуйте запросить страницу с помощью http://, вместо https://, чтобы понять, заключается ли проблема в веб-сервере или в SSL-соединении. Учтите, что в приведенных выше установках, корневые каталоги веб-сервера разные для http:// и https://, так что вы не можете (или не должны!) получить доступ к тому же содержимому. Если ваша тестовая страница в корневом каталоге http:// работает, в то время, как тестовая страница в корневом каталоге https:// не работает, это поможет вам более точно указать на проблему.

Если проблема в SSL соединении, удобным инструментом будет s_client, который является диагностической утилитой для решения проблем в TLS/SSL-соединениях. Обычное его использование: /usr/bin/openssl s_client -connect localhost:443. Также существует множество других опций, которые вы можете узнать из документации. Если вы получили сообщения об ошибках, это должно вам помочь в определении проблемы.

Заключение.

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

By sysadmin on | FreeBSD, Linux
Метки: , , , ,

Веб-сервер lighttpd

До недавнего времени, Apache не имел серьезных конкурентов с открытым исходным кодом. В последнем обзоре веб-серверов, проведенном Netcraft, мы можем видеть нечто новое. Как и обычно, Apache возглавляет список, Microsoft IIS второй, а знаменитый unknown — третий. Четвертым является Sun Java Web Server (ранее известный как ONE, бывший iPlanet, бывший Netscape). Но пятым номером, обслуживая около 1,4 миллиона сайтов, нечто под названием lighttpd. Откуда это взялось? Мы изучим историю lighttpd, начальную установку и настройку, а также некоторые взгляды на будущее проекта.

Вы можете произносить это название как лайт-ти-пи-ди или, меньше плюясь, лайти. Как бы вы не говорили/выплевывали название этого веб-сервера, вы найдете много информации на его веб-сайте, вики, блоге, или на форумах. lighttpd проектировался как высокоэффективный веб-сервер с низким использованием ресурсов. Он использует гораздо меньше памяти, чем Apache и, как правило, работает быстрее. lighttpd тихо усиливает много высоконагруженных сайтов, включая YouTube, Wikipedia, Meebo и A List Apart; вы увидете, что он часто используется вместо Apache вместе с популярными инструментами, такими как Ruby on Rails и Trac.

Что не так с Apache?

Не смотря на свою популярность, иногда использование Apache не является лучшим решением. Apache предоставляет различные Мульти-Процессные Модели (MPMs) для использования в различных средах работы. Модель prefork — наиболее популярная в Linux — создает определенное число процессов Apache при его запуске и управляет ими в пуле. Альтернативной моделью является worker, которая использует несколько потоков вместо процессов. Хотя потоки легче, чем процессы, вы не можете их использовать до тех пор, пока весь ваш сервер не будет безопасен для потоков (thread safe). Хотя Apache и mod_php — безопасны для потоков, это не гарантирует, что все сторонние модули могут использоваться. Сайт PHP не одобряет использование Apache 2 с потоковой MPM; это замедляет переход разработчиков с Apache 1.3 на 2.x. А модель prefork имеет свои проблемы: каждый процесс (Apache + PHP + сторонние модули) занимает много памяти (30 МБ не является чем-то необычным). Когда вы увеличиваете число одновременных процессов Apache, доступная вам память может быстро кончиться.

lighttpd в тумане.

Некоторые сайты параллельно обрабатывают тысячи файлов, будучи при этом ограничены в памяти и максимальным числом потоков или процессов. Дэн Кегел (Dan Kegel) подробно описал проблемы при обработки тысяч одновременных запросов на своей странице в C10K problem. В 2003 немецкий разработчик MySQL по имени Ян Кнешке (Jan Kneschke) заинтересовался в этой проблеме и решил, что сможет написать веб-сервер, который будет быстрее Apache, сфокусировавшись на правильных методиках. Он спроектировал lighttpd как один процесс с одним потоком и неблокирующимся вводом-выводом. Вместо select, он использовал быстрейшие обработчики событий в целевой системе: poll, epoll, kqueue или /dev/poll. Он выбрал безэкземлярные системные вызовы, как sendfile вместо read и write. В течение нескольких месяцев lighttpd стал обрабатывать статичные файлы быстрее, чем Apache.

Следующим шагом было обработать динамические (CGI) приложения, в частности PHP. Кнешке сдул пыль с FastCGI, разработанном Open Market в самых ранних днях существования интернета, в целях улучшения работы CGI. Вместо того, чтобы веб-сервер запускал ту же внешнюю CGI-программу при каждом вызове, FastCGI по существу был демоном для предварительного запуска CGI-приложения и управления связью между ним и веб-сервером. Это было быстрее, но Perl и PHP позже были внедрены в Apache в качестве модулей, которые были даже быстрее и получали доступ к внутренним действиям Apache по обработке HTTP. FastCGI для Apache стал пренебрегаться, но после того, как он был добавлен в lighttpd и к нему подключили PHP, его производительность равнялась или превышала ту, что показывал Apache с mod_php. В качестве дополнения, в реализацию lighttpd была добавлена автоматическая балансировка загрузки.

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

Установка lighttpd.

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

    # wget http://www.lighttpd.net/download/lighttpd-1.4.13.tar.gz
    # tar xvzf lighttpd-1.4.13.tar.gz
    # cd lighttpd-1.4.13
        # ./configure
    # make
    # make install

Это установит lighttpd в /usr/local. Если сборка не удалась, проверьте, что требуемые пакеты разработки pcre и zlib установлены в вашей системе.

Если вы хотите запускать и останавливать lighttpd вручную, то вперед. А чтобы установить lighttpd как сервис вроде Apache, отредактируйте и установите скрипт инициализации:

    # sed -e 's/FOO/lighttpd/g' doc/rc.lighttpd &gt; lighttpd.init
    # chmod a+rx lighttpd.init
    # cp lighttpd.init /etc/init.d/lighttpd
    # cp -p doc/sysconfig.lighttpd /etc/sysconfig/lighttpd
    # install -Dp ./doc/lighttpd.conf /etc/lighttpd/lighttpd.conf
        # chkconfig lighttpd on

Начальная настройка.

С виду синтаксис файлов настройки lighttpd может иметь отличия от Apache. Примеры со страницы настройки из вики выглядят больше похожими на Perl (или PHP, или Python), нежели чем на стиль XML httpd.conf в Apache. Для простого сайта со статическими файлами, вам нужно указать те же вещи, что и в Apache: document root, расположение access и error логов и имена user и group для работы сервера. Вот эквивалентные варианты Apache (httpd.conf) и lighttpd (lighttpd.conf):

Apache:

DocumentRoot /var/www/html
 
CustomLog /var/www/logs/access
 
ErrorLog /var/www/logs/error
 
User www
 
Group www

lighttpd:

server.document-root = "/var/www/html"
 
accesslog.filename = "/var/www/logs/access"
 
server.errorlog = "/var/www/logs/error"
 
server.username = "www"
 
server.groupname = "www"
 
server.modules = ( "mod_accesslog" )

Механизм включения модулей в lighttpd похож на тот, что в Apache, так что файл lighttpd.conf не должен расти. Чтобы использовать дополнительный модуль, вам нужно включить его и установить его опции. В Apache это делается с помощью LoadModule, а lighttpd просто включает незакомментированный модуль в массиве server.modules. Пока что вам нужен только mod_accesslog.

Аутентификация и авторизация.

lighttpd не поддерживает файлы .htaccess, так что вам нужно указывать все настройки в файле lighttpd.conf, или в файлах, к нему подключенным. Он понимает файлы пользователей Apache для простой и общей аутентификации, но поддержка групповых файлов ещё не реализована. Вот пример, как защитить паролем высокоуровневый каталог под названием special:

Apache:

  AuthName "My Special Directory"
 
  AuthType Basic
 
  AuthUserFile /var/www/passwords/users
 
  Order deny,allow
 
  require valid-user

lighttpd:

auth.backend = "htpasswd"
 
auth.backend.htpasswd.userfile = "/var/www/passwords/users"
 
auth.require = ( "/special/" =&gt;
 
  (
 
  "method"   =&gt; "basic",
 
  "realm"    =&gt; "My Special Directory",
 
  "require"  =&gt; "valid-user"
 
  )
 
)

Виртуальные хосты.

Вот другая задача для вашего нагруженного и недооцененного веб-сервера: управлять двумя сайтами с названиями scratch.example.com и sniff.example.com:

Apache:

NameVirtualHost *
 
  ServerName "scratch.example.com"
 
  DocumentRoot "/var/www/hosts/scratch/docs"
 
  ServerName "sniff.example.com"
 
  DocumentRoot "/var/www/hosts/sniff/docs"

lighttpd:

$HTTP["host"] == "scratch.example.com" {
 
  server.document-root = "/var/www/hosts/scratch/docs/" }
 
$HTTP["host"] == "sniff.example.com" {
 
  server.document-root = "/var/www/hosts/sniff/docs/" }

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

Apache:

LoadModule vhost_alias_module modules/mod_vhost_alias.so
 
VirtualDocumentRoot /var/www/hosts/%1/docs

lighttpd:

server.modules = ( ..., "mod_evhost", ... )
 
evhost.path-pattern = "/var/www/hosts/%3/docs"

Server-Side Includes (SSI)

Первым шагом к динамическому контенту будет простое включение SSI для файлов с расширением .shtml:

Apache:

AddHandler server-parsed .shtml

lighttpd:

server.modules = ( ..., "mod_ssi", ... )
 
ssi.extension = ( "shtml" )

PHP

lighttpd оптимизирует производительность обработки статичного файла с помощью выгрузки динамического контента, загружающего ЦПУ в другой процесс. Вместо обработки PHP внутри, как делает Apache с mod_php, lighttpd передает эту задачу FastCGI. Следующие примеры конфигурации превращают скучные, безжизненные .php-файлы в живые PHP скрипты. Чтобы ознакомиться с более пикантными деталями, чем те, что мы можем показать на этом сайте, посмотрите эту страницу.

Apache:

LoadModule php5_module modules/libphp5.so
 
AddType application/x-httpd-php .php

lighttpd:

server.modules = ( ..., "mod_fastcgi", ... )
 
fastcgi.server =
 
  ( ".php" =&gt;
 
    ( "localhost" =&gt;
 
      (
 
      "socket" =&gt; "/tmp/php-fastcgi.socket",
 
      "bin-path" =&gt; "/usr/local/bin/php"
 
      )
 
    )
 
  )

Достоинства lighttpd

lighttpd включает в себя модули, эквивалентные модулям Apache для сжатия, просмотра каталогов, пользовательских каталогов, SSL, WebDAV, перезаписи URL и переадресации. Вы можете прочитать об этом на сайте. Другие интересные модули lighttpd являются уникальными.

Если вы хотите сделать мини-YouTube, мы можете параллельно показывать тысячи флеш-роликов с помощью модуля mod_flv_streaming. YouTube обрабатывает его собственные статические файлы с помощью lighttpd, хотя ещё не использует этот модуль.

Если у вас есть такой сайт с большим количеством флеш-файлов, как вам защититься от хотлинкинга? Решением этой проблемы в lighttpd, подходящим для любых типов файлов, является mod_secdownload. Вы пишете функцию (примеры по ссылке написаны на PHP и Ruby) для генерирования специального URL, а модуль обрабатывает этот URL для предоставления доступа к определенному файлу на определенный период времени.

Лайти Один Пять Ноль.

В данный момент Кнешке разрабатывает версию 1.5.0, которая увеличит производительность и гибкость. Новая подсистема ввода-вывода улучшает производительность с помощью тредов (в данном случае треды имеют смысл) и асинхронный ввод-вывод, будь то POSIX, собственный в Linux или пользовательская оболочка gthread в glib 2.0.

Модуль mod_proxy_core объединяет три бэкенд модуля: mod-proxy, mod-fastcgi и mod-scgi. Отделение протоколов от основной обработки дает балансировку нагрузки (четырех видов!), преодоление отказа, удержание соединения и внутреннее формирование очереди к основной функции прокси.

Ожидается, что новый модуль под названием mod_magnet сыграет большую роль в будущем lighttpd. Он дает доступ к разным фазам HTTP запроса и ответа, включая задачи вроде перезаписи URL и генерации контента. Интересным выбором было использование в нем встроенного скриптового языка Lua вместо сложной грамматики, как в mod_rewrite Apache. Посмотрим, понравится ли это разработчикам, или они будут придерживаться знакомым, хотя иногда и сложным, правилам Apache.

Куда Лайти?

Кнешке видит будущее lighttpd в двух направлениях:

— Высокопроизводительные, широкодоступные поставщики контента

— Встроенные сервера, кросс-компиляция, использовать мало памяти

После 1.5.0, mod_magnet будет предоставлять больше динамической конфигурации сервера. Это может привлечь некоторых пользователей Apache, отказавшихся от перехода на lighttpd из-за отсутствия поддержки .htaccess. Я с нетерпением жду запланированную поддержку Comet — обратная сторона AJAX, в которой сервер обновляет клиента при поступлении новых данных. Это имеет приложения к панелям управления веб-приложений, чатам и другим высокоинтерактивным приложениям. С помощью AJAX и Comet, веб-приложения могут выглядеть гораздо более похожими на приложения с традиционным GUI. Но даже без этих новых возможностей, lighttpd уже является сильным конкурентом для Apache, особенно при ограничениях в памяти или обработке множества статических файлов. Легкость — это хорошо.

By sysadmin on 18.02.2009 | FreeBSD, Linux
Метки: , , , ,

Настройка синхронизации времени на сервере FreeBSD

Прописываем в /etc/rc.conf

    ntpdate_enable="YES"
    ntpd_enable="YES"

Первая строка будет запускать ntpdate при ребуте сервера чтобы система загрузилась с правильно установленными часами. Вторая строка запустит демон ntpd, который будет заведовать плавной корректировкой времени в дальнейшем.

Далее в /etc/ntp.conf пишем (рекомендуемые сервера с ntp.org)

    server 0.pool.ntp.org
    server 1.pool.ntp.org
    server 2.pool.ntp.org
    restrict 127.0.0.1

Строка restrict 127.0.0.1 разрешает управление демоном ntpd только с localhost (например для работы утилиты ntpd), можно вообще закрыть доступ написав restrict default ignore или разрешить только из локальной сети restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap — разрешит синхронизацию времени, но запретит настраивать сервер или быть равноправными участниками синхронизации времени.

И собственное все, подводим часы

    # /etc/rc.d/ntpdate start
    Setting date via ntp.
    23 Jan 00:56:48 ntpdate[928]: step time server 193.125.143.140 offset 0.027002 sec

и запускаем демон

    # /etc/rc.d/ntpd start
    Starting ntpd.

Смотрим что ntpd запустился нормально

    # ps ax|grep ntpd
    1044 ?? Ss 0:00,04 /usr/sbin/ntpd -c /etc/ntp.conf -p /var/run/ntpd.pid -f /var/db/ntpd.drift
    # tail /var/log/messages
    Jan 23 00:57:09 lola ntpd[1043]: ntpd 4.2.4p5-a Mon Jan 5 16:59:33 IRKT 2009 (1)
    # ntpq -p
         remote           refid      st t when poll reach   delay   offset  jitter
    ==============================================================================
     petrel.telecom. 192.36.143.150   2 u   60   64    1  119.017  5082.52   0.004
     hornet.itconnec 89.111.168.177   4 u   59   64    1  134.423  5086.05   0.004
     jane.telecom.mi 192.36.143.151   2 u   58   64    1  120.222  5086.08   0.004

Источник

By sysadmin on 15.02.2009 | FreeBSD
Метки: , ,