Quantcast
Channel: Библиотека знаний
Viewing all 1318 articles
Browse latest View live

Библиотека PHPWord: основные возможности - [Использование шаблонов]

$
0
0

Библиотека PHPWord: основные возможности

Библиотека PHPWord, находящаяся уже почти год в стадии бета-тестирования1), предоставляет возможность создания сложных документов формата OOXML (*.docx). Рассмотрим основные возможности этой библиотеки. Для начала работы достаточно распаковать архив с библиотекой в каталог с создаваемым вами документом PHP и подгрузить основной класс библиотеки, расположенный в файле PHPWord.php:

include_once'PHPWord.php';

Свойства документа и шрифт по-умолчанию

Создание документа начинается с объявления экземпляра класса PHPWord. Конструктор не требует передачи аргументов:

$word=new PHPWord();

Далее следует задать название и размер шрифта по-умолчанию:

$word->setDefaultFontName('Times New Roman');$word->setDefaultFontSize(14);

В рассматриваемой версии до применения указанных выше функций шрифтом по-умолчанию является Arial размером 20 пунктов. Теперь можно задать время создания документа, имя автора и так далее:

$meta=$word->getProperties();$meta->setCreator('Имя создателя документа');$meta->setCompany('Организация');$meta->setTitle('Название документа');$meta->setDescription('Описание документа');$meta->setCategory('Категория документа');$meta->setLastModifiedBy('Имя последнего редактора');$meta->setCreated(mktime(0,0,0,5,12,2011));// Дата и время создания документа$meta->setModified(time());//Дата и время последнего изменения документа$meta->setSubject('Тема документа');$meta->setKeywords('ключевые, слова, документа');

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

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

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

Раздел может иметь книжную или альбомную ориентацию, настраиваемые поля (margins), настраиваемые цвета границ раздела и их толщину (на рисунке показана пунктиром):

Параметр Описание
orientation Ориентация страницы:
null - книжная ориентация,
landscape - альбомная
marginTop Размер верхнего поля во внутренних единицах
marginRight Размер правого поля во внутренних единицах
marginBottom Размер нижнего поля во внутренних единицах
marginLeft Размер левого поля во внутренних единицах
borderTopSize Толщина верхнего края рамки во внутренних единицах
borderRightSize Толщина правого края рамки во внутренних единицах
borderBottomSize Толщина нижнего края рамки во внутренних единицах
borderLeftSize Толщина левого края рамки во внутренних единицах
borderTopColor Цвет верхнего края рамки в шестнадцатеричном формате
borderRightColor Цвет правого края рамки в шестнадцатеричном формате
borderBottomColor Цвет нижнего края рамки в шестнадцатеричном формате
borderLeftColor Цвет левого края рамки в шестнадцатеричном формате

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

function m2t($millimeters){returnfloor($millimeters*56.7);//1 твип равен 1/567 сантиметра}//m2t

Указанные в таблице параметры могут быть переданы в виде массива при создании раздела...

$sectionStyle=array('orientation'=>'landscape','marginLeft'=> m2t(15),//Левое поле равно 15 мм'marginRight'=> m2t(15),'marginTop'=> m2t(15),'borderTopColor'=>'C0C0C0');$section=$word->createSection($sectionStyle);

... или могут быть установлены по-отдельности после создания раздела:

$section=$word->createSection();$sectionStyle=$section->getSettings();$sectionStyle->setLandscape();//или setPortrait()$sectionStyle->setMarginLeft(m2t(15));$sectionStyle->setMarginRight(m2t(15));$sectionStyle->setBorderBottomSize(m2t(1));$sectionStyle->setBorderTopColor('C0C0C0');

Добавление текста

Добавление блока текста

Под блоком текста понимается отрывок текста, имеющий одинаковое форматирование (цвет, размер шрифта и т.п.). Для создания блока текста в выбранном разделе используйте функцию addText:

$section->addText($text,[$fontStyle[,$paragraphStyle]]);

Здесь $text - добавляемый текст, необязательный параметр $fontStyle - имя определенного ранее текстового стиля, необязательный параметр $paragraphStyle - имя определенного ранее стиля абзаца.

Изменение форматирования текста

Форматирование текста, как и форматирование раздела, может осуществляться при его создании...

$fontStyle=array('color'=>'FFFF00','size'=>18,'bold'=>true);$section->addText('Привет!',$fontStyle);//Массив с параметрами форматирования передается при создании

... или устанавливается после создания предназначенными для этого методами:

$text=$section->addText('Привет!');$style=$text->getStyle();$style->setColor('FFFF00');$style->setSize(18);$style->setBold();

Ниже приведен полный список доступных параметров форматирования текста:

Параметр Описание
size Размер шрифта в типографских пунктах
name Название шрифта (кегль)
bold Является ли текст полужирным (true\false)
italic Выделен ли текст курсивом (true\false)
superScript Является ли текст надстрочным (true\false)
subScript Является ли текст подстрочным (true\false)
underline Вид подчеркивания2)из набора констант PHPWord_Style_Font:
UNDERLINE_NONE - нет подчеркивания,
UNDERLINE_DASHHEAVY - жирная штриховая линия,
UNDERLINE_DASHLONG - удлиненная штриховая линия,
UNDERLINE_DASHLONGHEAVY - удлиненная жирная штриховая линия,
UNDERLINE_DOUBLE - двойная линия,
UNDERLINE_DOTHASH3) - штрих-пунктир,
UNDERLINE_DOTHASHHEAVY - жирный штрих-пунктир,
UNDERLINE_DOTDOTDASH - две точки + тире,
UNDERLINE_DOTDOTDASHHEAVY - жирные две точки + тире,
UNDERLINE_DOTTED - пунктир,
UNDERLINE_DOTTEDHEAVY - жирный пунктир,
UNDERLINE_SINGLE - одинарная линия,
UNDERLINE_WAVY - волнистая линия,
UNDERLINE_WAVYDOUBLE - двойная волнистая линия,
UNDERLINE_WAVYHEAVY - тройная волнистая линия,
UNDERLINE_WORDS - подчеркивать только слова (не подчеркивать пробелы)
Color Цвет шрифта в шестнадцатеричном формате
fgColor Цвет выделения маркером из набора констант PHPWord_Style_Font:
FGCOLOR_YELLOW - желтый,
FGCOLOR_LIGHTGREEN - ярко-зеленый,
FGCOLOR_CYAN - бирюзовый,
FGCOLOR_MAGENTA - лиловый,
FGCOLOR_BLUE - синий,
FGCOLOR_RED - красный,
FGCOLOR_DARKBLUE - темно-синий,
FGCOLOR_DARKCYAN - сине-зеленый,
FGCOLOR_DARKGREEN - темно-зеленый,
FGCOLOR_DARKMAGENTA - фиолетовый,
FGCOLOR_DARKRED - темно-красный,
FGCOLOR_DARKYELLOW - коричнево-зеленый,
FGCOLOR_DARKGRAY - серый 50%,
FGCOLOR_LIGHTGRAY - серый 25%,
FGCOLOR_BLACK - черный

Названия параметров должны употребляться с соблюдением регистра. В случае параметров underlineи fgColorприменение значений, не указанных в таблице, не допускается.

Cписок доступных параметров форматирования абзаца:

Параметр Описание
align Выравнивание текста в абзаце:
left - по левому краю,
right - по правому краю,
center - по центру,
both или justify - по ширине
spaceBefore Отступ абзаца сверху в твипсах
spaceAfter Отступ абзаца снизу в твипсах
spacing Интервал между строк в твипсах

Определение стилей текста и абзаца

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

$word->addFontStyle($styleName,$fontStyle);

Здесь $styleName - заданное вами имя стиля, $fontStyle - массив, содержащий определение стиля. После создания стиля его имя можно использовать при создании блоков текста, например:

$fontStyle=array('color'=>'006699','size'=>18,'italic'=>true, underline=>PHPWord_Style_Font::UNDERLINE_DOUBLE);$word->addFontStyle('myTextStyle',$fontStyle);//myTextStyle - это имя стиля$text=$section->addText('Привет!','myTextStyle');

Аналогичным образом осуществляется создание стиля абзаца:

$paragraphStyle=array('color'=>'006699','size'=>18,'italic'=>true, underline=>UNDERLINE_DOUBLE);$word->addParagraphStyle('myParagraphStyle',$paragraphStyle);$text=$section->addText('Привет!','myTextStyle','myParagraphStyle');

Группировка блоков текста в абзац

Блоки текста с различным форматированием могут быть объединены в абзац заданного вида. Для этого применяется команда createTextRun:

$textrun=$section->createTextRun([$paragraphStyle]);$textrun->addText('Полужирный текст',array('bold'=>true));$textrun->addText('Курсив',array('italic'=>true));$textrun->addText('Цветной текст',array('color'=>'AACC00'));

Необязательный параметр $paragraphStyle - массив со стилем абзаца или название созданного ранее именованного стиля.

Добавление заголовков

В библиотеке имеются отдельные функции для добавления заголовков (addTitle) и задания их стилей (addTitleStyle). Применение заголовков вместо форматированных блоков текста необходимо в том случае, если вы хотите добавить в документ автоматически создаваемое оглавление, поскольку в оглавление включаются только заголовки, а не обычные блоки текста. При добавлении заголовков создание стилей заголовков обязательно:

$word->addTitleStyle($titleLevel[,$fontStyle[,$paragraphStyle]]);

Здесь $titleLevel - уровень заголовка, для которого задается стиль (обычно от 1 до 6), $fontStyle - массив со стилем форматирования заголовка, $paragraphStyle - массив со стилем форматирования абзаца. Как видите, форматирование можно не трогать, но сам стиль заголовка требуемого уровня должен быть обязательно создан. Добавление заголовка делается так:

$section->addTitle($text[,$titleLevel]);

По-умолчанию создается заголовок 1 уровня.

Добавление ссылок

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

$section->addLink($url,[$text[,$fontStyle[,$paragraphStyle]]]);

Здесь $url - URLссылки. В случае, если $text не указана в качестве отображаемого текста, используется URL. Не знаю зачем, но для изменения форматирования ссылок используется отдельная функция addLinkStyle. Ее аргументы полностью совпадают с аргументами addFontStyle. Если требуется указать название стиля, но переменную $textхочется оставить пустой, передайте ей значение null:

$section->addLink('http://www.phpexport.ru/',NULL,'myLinkStyle');

Разрыв строки и страницы

Для принудительного переноса строки используйте синтаксис:

$section->addTextBreak([$num]);

Необязательный параметр $num, по-умолчанию равный 1, указывает сколько переносов строки необходимо сделать. Для принудительной вставки разрыва страницы выполните:

$section->addPageBreak();

Добавление оглавления

Для добавления оглавления используется функция addTOC:

$section->addTOC([$fontStyle[,$tocStyle]]);

Здесь $fontStyle - форматирование текста, определенное одним из ранее указанных способов, $tocStyle - массив со стилем оформления оглавления, возможные параметры которого приведены в таблице: ^ Параметр ^ Описание ^

tabLeader Заполнитель между заголовком и номером страницы из набора констант PHPWord_Style_TOC:
TABLEADER_DOT - точки,
TABLEADER_UNDERSCORE - символ подчеркивания,
TABLEADER_LINE - линия,
TABLEADER_NONE - нет заполнителя
tabPos Положение номера страницы в твипсах
Indent Отступ заголовков в твипсах

Добавление списков

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

$section->addListItem($text[,$depth[,$textStyle[,$listStyle[,$paragraphStyle]]]]);

Здесь $text - текст добавляемого элемента списка, $depth - глубина вложенности элемента в списке (от 1 до 9, по-умолчанию равна 1), $textStyle - форматирование текста списка одним из предложенных ранее способов, $listStyle - форматирование самого списка при помощи массива параметров, $paragraphStyle - форматирование абзаца. На данный момент не существует функции addListStyle, поскольку у списков пока может изменяться только один параметр:

Параметр Описание
listType Вид списка из набора констант PHPWord_Style_ListItem:
TYPE_NUMBER - одноуровневый нумерованный список,
TYPE_NUMBER_NESTED - многоуровневый нумерованный список,
TYPE_BULLET_FILLED - ненумерованный список с маркерами в виде закрашенных кругов,
TYPE_BULLET_EMPTY - ненумерованный список с маркерами в виде незакрашенных кругов,
TYPE_SQUARE_FILLED - ненумерованный список с маркерами в виде закрашенных квадратов

Добавление таблиц

Важной частью документа Word являются таблицы. Для создания таблицы в PHPWord выполните:

$table=$section->addTable([$tableStyle]);

Необязательный аргумент $tableStyle - массив с описанием стиля таблицы или название такового, определенного методом addTableStyle:

$word->addTableStyle($styleName,$tableStyle[,$firstRowStyle]);

Аргументы: $styleName - название стиля, $tableStyle - массив с определением стиля, $firstRowStyle - массив с определением стиля ячеек 1 строки (шапки) таблицы. Ниже приведена таблица возможных стилевых параметров таблицы в целом: ^ Параметр ^ Описание ^

cellMarginTop Отступ от ячейки сверху в твипсах
cellMarginRight Отступ от ячейки справа в твипсах
cellMarginBottom Отступ от ячейки снизу в твипсах
cellMarginLeft Отступ от ячейки слева в твипсах

Теперь в созданную таблицу можно добавить ячейки. Как и в XHTML, вначале нужно создать строку...

$table->addRow([$rowHeight]);

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

$cell=$table->addCell([$cellWidth[,$cellStyle]]);$cell->addText('Текст ячейки');

... или сделать то же самое одной командой...

$table->addCell([$cellWidth[,$cellStyle]])->addText('Текст ячейки');

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

Команда Действие
addText Добавить форматированный текст
addTextBreak Добавить перенос строки
addLink Добавить ссылку
addListItem Добавить элемент списка
addImage Добавить изображение из файла
addMemoryImage Добавить динамически сгенерированное изображение
addObject Добавить объект OLE
addPreserveText Добавить поле (например, нумерацию страниц)

Как вы уже, наверное, догадались, параметр $rowHeight - позволяет задать высоту в твипсах создаваемой строки, $cellWidth - ширину ячейки (столбца), а $cellStyle - изменить форматирование ячейки. При форматировании ячейки поддерживаются следующие параметры:

Параметр Описание
valign Выравнивание в ячейке по-вертикали: both - по-вертикали по ширине,
top - по верхнему краю,
bottom - по нижнему краю,
center - по-центру
textDirection Направление текста из набора констант PHPWord_Style_Cell:
TEXT_DIR_BTLR - развернут на 90 градусов против часовой стрелки,
TEXT_DIR_TBRL - развернут на 90 градусов по часовой стрелке
bgColor Цвет фона ячейки в шестнадцатеричном формате
borderTopSize Толщина верхней границы ячейки в твипсах
borderRightSize Толщина правой границы ячейки в твипсах
borderBottomSize Толщина нижней границы ячейки в твипсах
borderLeftSize Толщина левой границы ячейки в твипсах
borderTopColor Цвет верхней границы ячейки в шестнадцатеричном формате
borderRightColor Цвет правой границы ячейки в шестнадцатеричном формате
borderBottomColor Цвет нижней границы ячейки в шестнадцатеричном формате
borderLeftColor Цвет левой границы ячейки в шестнадцатеричном формате

Добавление изображений

PHPWord позволяет добавлять в создаваемый документ изображения 2 типов: из файла (метод addImage) и динамически сгенерированное сценарием изображение (метод addMemoryImage). Поддерживаются файлы форматов jpg, png, gif, tiff, bmp. Примеры применения методов:

$section->addImage($src[,$imageStyle]);$section->addMemoryImage($url[,$imageStyle]);

Здесь $srcи $url - соответственно путь к файлу и абсолютный путь к сценарию (с адресом сайта и промежуточных каталогов), $imageStyle - массив с форматированием изображения. Поддерживаемые параметры форматирования:

Параметр Описание
width Требуемая ширина изображения в пикселях
height Требуемая высота изображения в пикселях
align Горизонтальное выравнивание изображения:
left - по левому краю,
right - по правому краю,
center - по центру

Если требуемые размеры изображения не указаны - библиотека пытается определить фактические размеры изображения при помощи функции [php>getimagesize|getimagesize]].

Добавление объектов OLE

С помощью метода addObjectвы можете внедрить в создаваемый документ фрагмент другого документа (*.docx, *.xlsx, *.pptx) при помощи технологии OLE:

$section->addObject($src[,$objectStyle]);

Массив $objectStyleможет содержать только один параметр:

Параметр Описание
align Выравнивание объекта по-горизонтали:
left - по левому краю,
right - по правому краю,
center - по центру

Колонтитулы

Каждый раздел документа может иметь свой верхний (header) и нижний (footer) колонтитул, отображаемый на всех принадлежащих ему страницах. С точки зрения Word колонтитул является особым видом раздела, поэтому к колонтитулу применимо большинство описанных выше методов: addText, createTextRun, addTextBreak, addImage, addMemoryImage, addListItem, addTable. Кроме этого колонтитул имеет собственный метод addPreserveText, позволяющий создавать нумерацию страниц. Пример создания верхнего (createHeader) и нижнего (createFooter) колонтитула:

//Верхний колонтитул со статическим текстом$header=$section->createHeader();$header->addText('Этот документ создан Vania-pooh при помощи PHPWord!');//Нижний колонтитул с нумерацией страниц посередине$footer=$section->createFooter();$footer->addPreserveText('Страница {PAGE} из {NUMPAGES}.',array('bold'=>true),array('align'=>'center'));

Как и всегда форматирование текста колонтитула и абзаца являются необязательными параметрами.

Использование шаблонов

Библиотека PHPWord поддерживает еще один интересный метод создания документов Word - использование шаблонов. Подробный принцип работы при генерировании документов из шаблонов описан в статье docx-templates. В качестве метки в PHPWord используется комбинация ${NAME}, где NAME - имя метки. Пример генерирования с использованием меток:

$template=$word->loadTemplate('template.docx');//Загружаем шаблон$template->setValue('Name','Иванов');//Производим замену метки на значение$template->setValue('Surname','Иван');//И еще одну метку$template->save('document.docx');//Сохраняем результат в файл

Сохранение файла

Для сохранения файла на жесткий диск или вывода его для скачивания пользователю используется метод saveкласса PHPWord_Writer_Word2007. В качестве единственного аргумента метода указывается строка 'php://output', если требуется вывести документ для скачивания пользователем или имя файла, если документ нужно сохранить на жесткий диск. При выводе файла для скачивания не забудьте отправить браузеру пользователя соответствующие заголовки:

header('Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');header('Content-Disposition: attachment;filename="document.docx"');header('Cache-Control: max-age=0');$writer= PHPWord_IOFactory::createWriter($word,'Word2007');$writer->save('php://output');

Сохранение файла на жесткий диск:

$writer= PHPWord_IOFactory::createWriter($word,'Word2007');$writer->save('filename.docx');

Пример

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

Текст примера появится несколько позже, когда автор сможет сгенерировать документ с кириллицей (на английском работает). Проблема связана с функцией utf8_encode, используемой в PHPWord. Если у вас есть решение этой проблемы, просьба отписаться.
Update! Проблема с функцией utf8_encode и кириллической кодировкой решается если заменить функцию на iconv и указать входящую кодировку CP1251 и выходе UTF8. Сделать это надо во всех местах библиотеки где используется функция utf8_encode.

Данный пример в работе можно посмотреть по этой ссылке. В заключение хотелось бы отметить, что для сайтов, где структура docx-файла слабо4)зависит от входных данных, рекомендуемым способом стоит считать docx-templates, поскольку:

  • Механизм шаблонов должен работать быстрее, так как основная структура документа уже создана до выполнения сценария5)
  • Можно создавать документы любой сложности. Библиотека же всегда будет иметь ограничения.
  • Шаблон может быть создан в самой свежей версии Microsoft Word и будет учитывать все возможные изменения внесенные создателями программы
  • В случае, если в зависимости от исходных данных документ может иметь несколько разных представлений, можно создать ровно такое же число разных шаблонов
1)
на 07.05.2011 библиотека имеет версию 0.6.2 от 25.07.2010
2)
Все возможные виды подчеркивания можно посмотреть в диалоге Шрифт Microsoft Word
3)
Вообще должно быть UNDERLINE_DOTDASH, видимо опечатка в коде
4)
То есть в худшем случае существует конечное число возможных видов генерируемого документа, а в лучшем случае все документы выглядят одинаково, меняются только пользовательские данные.
5)
Но я не проверял так ли это на самом деле

BASH, SH - [Переменные и конфиг файлы]

$
0
0

BASH, SH

Переменные и конфиг файлы

                     +-----------------+   +------FIRST-------+   +-----------------+
                     |                 |   | ~/.bash_profile  |   |                 |
login shell -------->|  /etc/profile   |-->| ~/.bash_login ------>|  ~/.bashrc      |
                     |                 |   | ~/.profile       |   |                 |
                     +-----------------+   +------------------+   +-----------------+
                     +-----------------+   +-----------------+
                     |                 |   |                 |
interactive shell -->|  ~/.bashrc -------->| /etc/bashrc     |
                     |                 |   |                 |
                     +-----------------+   +-----------------+
                     +-----------------+
                     |                 |
logout shell ------->|  ~/.bash_logout |
                     |                 |
                     +-----------------+
  • []-->[] means source by workflow (Automatically).
  • [--->[] means source by convention (Manually. If not, nothing happen.).
  • FIRST means find the first available, ignore rest

Несколько примечаний:

  • «интерактивная оболочка» должна быть «интерактивной оболочкой без входа в систему», а «оболочка входа в систему» ​​должна быть «интерактивной оболочкой входа в систему».
  • Кроме того, по крайней мере, в Ubuntu, для интерактивных оболочек без входа в систему /etc/bash.bashrc сначала читается ~/.bashrc. Обратите внимание, что /etc/bash.bashrc его нет в ванильном GNU Bash, это модификация, которую делают многие дистрибутивы.

Согласно мануалу по bash, .bash_profile исполняется для оболочек, осуществляющих авторизацию пользователя. .bashrc исполняется для интерактивных оболочек, не авторизующих пользователя.

Документация

Программирования

Видео уроки

Применить настройки

  • source ~/.bashrc

Примеры конфигурационных файлов

Примеры

Замена текста в файлах с возможностью рекурсии

find ./ -type f -exec sed -i 's/CHARSET=utf8/CHARSET=cp1251/g' {} \;

Прогрессбар

Видео уроки

RUS

ENG

Алгоритм выбора location в Nginx

$
0
0

Алгоритм выбора location в Nginx

root VS alias

location /ks/ {
        root /opt/images/;
}
# /opt/images/ks
location /ks/ {
        alias /opt/images/;
}
# /opt/images

С одним уровнем вложенности

  • Вначале будет искаться равенство (=) . Оно имеет высший приоритет.
  • Потом будет искаться максимальный по длине префиксный location , после чего будет проверено, есть ли на найденном location модификатор приоритета (^~), и если он есть, то будет возвращён этот location.
  • Потом будут проверяться регулярные выражения ((~) и (~*)) сверху вниз. При совпадении будет возвращён первый location из них.
  • Потом вернётся тот префиксный location, который мы нашли до этого.

С вложенными location

Стартуем с верхнего уровня. Если на текущем уровне выполняется равенство (=) , поиск прекращается — это и будет результат, т. к. такой location не может иметь никаких других вложенных location. В противном случае ищем на текущем уровне самый большой префиксный location 1)) . Если такой префиксный location существует, то делаем его текущим уровнем и переходим к п. 2. В противном случае выходим из цикла. Мы вышли из цикла. На данный момент мы нашли «самый большой» префиксный location, но не думайте, что это самый большой из всех. Пример:

location /abc {
    location /abcdefghi {
        …
    }
}

location /abcdef {
    …
}

В данном примере мы перейдём в /abcdef, т. к. на его уровне он переборол более короткий /abc. Но по факту существуют location и больше него. Теперь в найденном location мы ищем первый верный regexp. При нахождении поиск полностью прекращается. Обратите внимание: в этом пункте мы по факту ищем regexp на самом нижнем уровне, а не на верхнем, как многие могли бы подумать. Т. е. поиск regexp идёт снизу, а не сверху (но внутри одного уровня идёт сверху, а не снизу). Далее, если ничего не найдено, поднимаемся на один уровень вверх и аналогично ищем первый regexp, но в этот раз уже только при условии, что location, в котором мы были до этого, не имел метки (^~). Повторяем этот пункт до тех пор, пока подниматься будет некуда. При этом нужно иметь ввиду: Даже если какой-то из уровней имеет метку (^~), это не значит, что мы не осуществляем подъём. Подъём осуществляется всегда, но если более нижний уровень имел метку (^~), то на текущем уровне поиск regexp'ов не проводится. Возможности запретить проверку regexp в самом нижнем уровне нет — для этого нужно создать ещё один вложенный уровень. А вот запретить проверку regexp на нулевом уровне можно — для этого location первого уровня (который находится на нулевом уровне) должен иметь метку (^~). Мы сделали подъём по дереву, но так и не нашли ни одного regexp. Раз regexp не найден, возвращаем «почти самый большой» префиксным location, который был найден ранее. Готово.

NGINX - [NGINX]

$
0
0

NGINX

Скрипт создания настроек сайта для Nginx

Я очень давно разрабатываю web проекты и для их публикации использую nginx web сервер. За это время скопилось много рецептов использования этого замчательного web сервера. Но из за лени каждый раз писать настройки заново я создал скрипт позволяющий ускорить и упростить это муторное занятие.

Параметры сервера

  • client_max_body_size
  • keepalive_timeout

Встроенные переменные

Конструкции и их применение

  • if - не использовать
  • break
  • try_files

Модули / Modules

Рецепты / Рекомендации

Примеры конфигураций

Vue.Js Framework - [RU]

$
0
0

Vue.Js Framework

В отличие от фреймворков-монолитов, Vue создан пригодным для постепенного внедрения. Его ядро в первую очередь решает задачи уровня представления (view), что упрощает интеграцию с другими библиотеками и существующими проектами. С другой стороны, Vue полностью подходит и для создания сложных одностраничных приложений (SPA, Single-Page Applications)

Популярные компонеты

Расширения / Компоненты / Процессоры

Каталоги

Ссылки

Обучение / Трюки / Статьи

Видео

RU

En

Back-end / Разработка приложений на стороне сервера - [Back-end / Разработка приложений на стороне сервера]

$
0
0

Back-end / Разработка приложений на стороне сервера

Back-end database / Разработка и настройка баз данных

Серверное программирование и утилиты

Front-end / Разработка приложений для сайтов

App / Разработка приложений под разные платформы

Системы анализа и статистики

Документация - создано

Model-View-Controller

$
0
0

VC (Model-View-Controller) — фундаментальный шаблон проектирования, целью которого является отделение логики интерфейса пользователя от логики программирования. MVC имеет множество вариантов реализации. Существуют модификации шаблона, самые известные из них MVP и MVVM. Ниже описана концепция архитектурного шаблона MVC и его модификаций MVP и MVVM. Приведена концепция шаблона MVA, основанная на паттернах MVC, MVP и MVVM и адаптирована под язык ABAP.

Model-View-Controller

Model (модель) — содержит модель данных и бизнес-логику. Иными словами, модель делает все для чего создавалась программа. View (представление) — интерфейс взаимодействия с пользователем. Представление отображает часть данных модели пользователю. В некоторых случаях, представление может иметь свою бизнес-логику. Controller (контроллер) — связывает модель и представление между собой. Контроллер обрабатывает события пользователя, управляет состоянием модели. Схема работы MVC Точкой входа в программу является контроллер. Контроллер имеет ссылки на модель и на представление. Контроллер подписывается на события представления, а представление подписывается на события модели. Когда пользователь совершает какие-нибудь действия, управление переходит к контроллеру и контроллер воздействует на модель. При изменении модели идет воздействие контроллер получает соответствующее событие и воздействует на представление для обновления данных. В реализации MVC независимой частью является модель, она ничего не знает о представлении и контроллере. Если программа содержит несколько представлений (например, несколько ABAP-экранов), то для каждого представления требуется создать свой контроллер. При этом, допускается использовать одну и туже модель в разных контроллерах и представлениях. Реализация MVC в ABAP подробно описана в книге Design Patterns in ABAP Objects с примерами ALV и Web Dynpro представлений.

Model-View-Presenter

Компоненты Model и View в шаблоне MVP аналогичны соответствующим компонентам модели MVC. Основной целью данного шаблона является отделения модели от представления. В шаблоне MVP информация об изменении модели поступает на презентер (Presenter), который воздействует на представление для обновления состояния. Схема работы MVP Отсутствие связи между моделью и представлением позволяет сделать абстракцию представления. Реализовать данный паттерн можно путем выделения интерфейса представления IView. Интерфейс будет содержать набор методов и свойств, необходимых презентеру, сам презентер будет подписываться на события представления и вызывать методы для его обновления. Абстрагирование представления полезно в задачах, где требуется отобразить один и тот же набор данных в разных представлениях. Например, выводить отчет в разных форматах: ALV, PDF, EXCEL.

Model-View-ViewModel

Шаблон MVVM предназначен для разработки в WPF на языке C#. Но его идею можно применять и в ABAP. Идея данного паттерна заключается в отделении слов друг от друга. Слой View знает только о ViewModel, ViewModel знает только о Model. Схема работы MVVM Представление не требует реализации IView, для получения данных ему требуется передать ссылку на источник данных (DataContext). ViewModel является посредником между передачей данных от модели в DataContext, элементы представления ссылаются на источник данных через биндинги (Binding). Важное отличие MVVM от MVC и MVP то, что представление в MVVM может менять модель напрямую за счет двухстороннего биндинга. В случае с MVC и MVP представление имеет доступ «только на чтение» к данным модели.

Model-View-Application

Особенностью ABAP приложений является то, то представление может обновиться только после действий пользователя. Даже если какой-нибудь асинхронный процесс поменяет модель, то инициировать обновление представление он не сможет. Данная особенность позволяет ослабить связь модель-представление и делегировать функцию обновления представления самому представлению. Иными словами, представление само должно решать, когда надо обновить себя, а когда нет. Если взять за основу паттерны MVP и MVVM и принять во внимание отсутствие обратной связи от модели до представления, то можно спроектировать новый архитектурный шаблон MVA. Схема работы MVA

Концепция MVA

Реализация MVA основана на объектно-ориентированном подходе, где на каждый слой архитектуры будет реализован один или несколько классов. Каждый из слоев обладает рядом свойств. Представление (View и IView):

MVA работает с абстракцией представления IView. Все классы View должны содержать реализацию IView. IView содержит события, которые требуют взаимодействия с моделью IView содержит контекст — ссылка на данные модели, которые необходимо отобразить пользователю View может содержать бизнес-логику, которая не требует взаимодействия с моделью. Например, если требуется реализовать из ALV проваливание в карточку контрагента, то данная логика будет относиться к представлению.


Программный брокер сообщений

$
0
0

Программный брокер сообщений

Apache Kafkaговорят «тупой сервер, умный клиент», что означает необходимость реализации логики работы с сообщениями на клиентской стороне, т.е consumer заботится о получении нужных сообщений. RabbitMQ– наоборот, «умный сервер, тупой клиент», поскольку этот брокер сам обеспечивает всю логику работы с сообщениями.

Bash - [test]

$
0
0

Bash

Файлы конфигурации: .profile .bash_profile и .bashrc итд

В чем отличие .bash_profile и .bashrc?

.bash_profile загружается только при входе пользователя в систему (консольный вход, ssh), в то время как .bashrc запускается для интерактивных сервисов выполняемых без логина (запуск xterm).

Переменные и параметры

$$ pid текущего shell (самого процесса-сценария)
$! pid последнего процесса в фоновом режиме
$? код возврата последнего процесса (функции или скрипта)
$x где x — номер параметра, переданного скрипту ($1, $2 и т. д., $0 — последний запущенный скрипт)
$# количество аргументов командной строки
$* все аргументы в виде одной строки (слова)
$@ то же самое, что и $*, но при этом каждый параметр представлен как отдельная строка (слово)
$- список флагов, переданных сценарию
$_ содержит последний аргумент предыдущей команды

Потоки вывода и файловые дескрипторы

  • du -h 1 > ./log 2>&1
НаименованиеОписание
1Поток вывода
2Поток ошибок
&1обозначает файловый дескриптор 1

Конструкции

0-9

A

Массивы

array=( one two three )files=("/etc/passwd""/etc/group""/etc/hosts")limits=(10, 20, 26, 39, 48)

ARGV

# ------------- SCRIPT ------------- # 
#!/bin/bash 
echoecho"# arguments called with ---->  ${@}"echo"# \$1 ---------------------->  $1       "echo"# \$2 ---------------------->  $2       "echo"# path to me --------------->  ${0}"echo"# parent path -------------->  ${0%/*}"echo"# my name ------------------>  ${0##*/}"echoexit 
# ------------- CALLED ------------- # 
# Notice on the next line, the first argument is called within double, # and single quotes, since it contains two words 
$  /misc/shell_scripts/check_root/show_parms.sh "'hello there'""'william'" 
# ------------- RESULTS ------------- # 
# arguments called with --->  'hello there' 'william'# $1 ---------------------->  'hello there'# $2 ---------------------->  'william'# path to me -------------->  /misc/shell_scripts/check_root/show_parms.sh# parent path ------------->  /misc/shell_scripts/check_root# my name ----------------->  show_parms.sh 
# ------------- END ------------- #

B

C

case

case "$1" in
start)
esac

cut

микропрограмма для работы с текстом

Параметры:

  • -d
  • -f(число)

Переименовывает все файлы вида thread_1_seq_35970.1752.876204343 в файлы вида arch_1_0000035970_869578613.arc

#! /bin/bashFOUND=0for filename in*doecho"$filename"|grep-q"thread_1_seq_" 
  if[$?-eq$FOUND]; thenpart=`echo$filename|cut-d"_"-f4|cut-d"." -f1`mv"$filename""arch_1_00000${part}_869578613.arc"fi 
done

D

debug

Необходимо добавить параметр -x Пример:

# bash -x script.sh

dialog

Представляет из себя интерфейс для библиотеки ncurses. И позволяет строить диалоги из скрипта. Альтернативой dialog может служить whiptail, который даже присутствует в некоторых системах по умолчанию.

Dialog

#!/usr/bin/bash 
Choice=`$Dialog--stdout--clear--menu"Выберите файл"207114$Spisok`retval=$? 
case$retvalin0)esac

E

F

function

function f1{ 
	# params $1echo$1 
} 
f1 A

foreach

for fn in`cat filenames.txt`; doecho"the next file is $fn"cat$fndone
whileread filename
doecho"Printing: $filename"cat"$filename"done< filenames.txt
for fn incat filenames.txt; docat"$fn"; done
for i in"${arrayName[@]}"do
   :
   # do whatever on $idone

G

H

Choice="Y" 
cat<< EOF_CONFIG >$config
client
remote xxxxx
port 1194
proto udp
dev tun
ns-cert-type server
tls-client
reneg-sec 60
mtu-test
cipher AES-256-CBC
comp-lzo
persist-key
persist-tun
keysize 256
nobind
explicit-exit-notify 2
pkcs12 yyy/$Choice
EOF_CONFIG
 
echo$config

I

Индексы

  • [@] - Ссылка на копию массива в переменной $1
  • [*] - Строка
  • [n]
  • var=(1 2 3 4)
  • echo ${var[@]}

if

ifчто-то
then# делать тот-тоelse# делать тот-тоfi
ifчто-то; then# делать тот-тоelse# делать тот-тоfi

input

Запрос символа от пользователя

echo-n"Продолжить? (y/n) " 
read item
case"$item"in
    y|Y)echo"Ввели «y», продолжаем...";;
    n|N)echo"Ввели «n», завершаем..."exit0;;*)echo"Ничего не ввели. Выполняем действие по умолчанию...";;esac

J

K

L

M

N

O

echo

Вывод прогресс бара

$ echo-ne'#####                     (33%)\r'

P

Q

R

S

select

select action in"Опция 1""Опция 2""Выход"doecho$actiontest$action = "Выход"&&breakdone

T

test

  • Параметры:
    • -b file— истина, если file существует и является специальным блочным устройством.
    • -c file— истина, если file существует и символьное устройство.
    • -d file— истина, если file существует и является каталогом.
    • -e file— истина, если file существует.
    • -f file— истина, если file существует и является обычным файлом.
    • -g file— истина, если file существует и имеет установленным групповой идентификатор (set-group-id).
    • -k file— истина, если file имеет установленным «sticky» бит.
    • -L file— истина, если file существует и является символьной ссылкой.
    • -p file— истина, если file существует и является именованным каналом (pipe).
    • -r file— истина, если file существует и читаем.
    • -s file— истина, если file существует и имеет размер больше, чем ноль.
    • -S file— истина, если file существует и является сокетом.
    • -t [fd]— истина, если fd открыт на терминале. Если fd пропущен, по умолчанию 1 (стандартное устройство вывода).
    • -u file— истина, если file существует и имеет установленным бит пользователя (set-user-id).
    • -w file— истина, если file существует и записываем.
    • -x file— истина, если file существует и исполняем.
    • -O file— истина, если file существует и его владелец имеет эффективный идентификатор пользователя.
    • -G file— истина, если file существует и его владелец имеет эффективный идентификатор группы.
    • file1 -nt file2— истина, если file1 новее (дата модификации), чем file2.
    • file1 -ot file2— истина, если file1 старее, чем file2.
    • file1 -ef file2— истина, если file1 и file2 имеют то же устройство и номер inode.
    • -z string— истина, если длина string равна нулю.
    • -n string— истина, если длина string не ноль.
    • string1 = string2— истина, если строки равны.
    • string1 != string2— истина, если строки не равны.
    • ! expr— истина, если выражение expr ложь.
    • expr1 -a expr2— истина, если оба выражения expr1 и expr2 истина.
    • expr1 -o expr2— истина, если хотя бы одно из выражений expr1 или expr2 истина.
    • arg1 %оператор% arg2 -eq, -ne, -lt, -le, -gt, или -ge— эти арифметические бинарные операции возвращают истину, если arg1 равно (-eq), не равно (-ne), меньше чем (-lt), меньше чем или равно (-le), больше чем (-gt), или больше или равно (-ge), чем arg2, соответственно. arg1 и arg2 могут быть положительными целыми, отрицательными целыми, или специальными выражениями -l string, которые вычисляют длину string.
  • Сокращенный вариант [ ]

Применение в коде

if[$daynow!= 1]; then# ....fi 
if[$daynow-ge1]&&[$daynow-le7]; then# ....fi

Сравнение -eqс ==

$ [ a == a ]; echo$?0 
$ [ a -eq a ]; echo$?
-bash: [: a: integer expression expected
2

status

Проверка статуса выполнения программы

rm test_file
 
if[$?-eq0]; thenecho-n"$(tput hpa $(tput cols))$(tput cub 6)[OK]"echoelseecho-n"$(tput hpa $(tput cols))$(tput cub 6)[fail]"echofi

tput

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

  • tput hpa N — сдвиг курсора на N позиций
  • tput cols получает ширину окна терминала
  • tput cub 6 — сдвигает курсор на 6 позиций влево

Также можно выставить цвет

  • tput setaf 0..7 — цвет текста
  • tput setab 0..7 — цвет фона
  • tput sgr0 — сброс на дефолтный

Подробнее: http://www.ibm.com/developerworks/ru/library/au-learningtput/

U

V

W

X

Y

Перенаправление обработки скрипта в другую папку

$
0
0

Перенаправление обработки скрипта в другую папку

server{listen 192.168.1.1:80;server_name site.ztc ;root /home/site.ztc/httpdocs/app/frontend/web;indexindex.php;access_log /home/site.ztc/logs/access.log;error_log  /home/site.ztc/logs/error.log error;charset utf-8; 
                                # With PHP-FPMlocation / {indexindex.php;try_files$uri$uri/ /index.php?$query_string;} 
                                # PHP fastcgilocation~ \.php {include fastcgi_params;# Use your own port of fastcgi here#fastcgi_pass 127.0.0.1:9000;fastcgi_pass unix:/var/run/php-fpm-7-site.ztc.sock;fastcgi_indexindex.php;fastcgi_split_path_info ^(.+\.php)(/.+)$;fastcgi_param PATH_INFO $fastcgi_path_info;fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;} 
                                # rpclocation~ ^/rpc {alias /home/site.ztc/httpdocs/app/api/web;indexindex.php;try_files$uri$uri/ @rpc; 
                                                # PHP fastcgilocation~* \.php {include fastcgi_params;# Use your own port of fastcgi here#fastcgi_pass 127.0.0.1:9000;fastcgi_pass unix:/var/run/php-fpm-7-site.ztc.sock;fastcgi_split_path_info ^(.+\.php)(/.+)$;fastcgi_param SCRIPT_FILENAME $request_filename;}} 
                                location@rpc{rewrite ^/rpc/(.*)$ /rpc/index.php?$1 last;# THIS IS THE IMPORTANT LINE}# end rpc 
}
  • @rpc - Этот локейшен необходим для перенаправления c /rpc на /rpc/index.php. Указываем lastдля отключения дальнейшего реврайта
  • $request_filename - равносильно fastcgi_param SCRIPT_FILENAME /home/site.ztc/httpdocs/app/api/web/$script;

MySql Использование - [Запросы]

$
0
0

MySql Использование

 |

Оптимизация

Настройка MySQL

Рекомендуемая конфигурация, разбор параметров после. Пример сделан для ОС *NIX типа, как наиболее подходящей для высоконагруженных серверов БД. При необходимости его можно адаптировать для Windows системы, изменив соответственно пути файловой системы и пропустив секцию mysqld.safe.

Кодировка 1251 базы данных по-умолчанию - исторически сложившаяся и не изменяемая как не несущая в себе существенных неудобств. Но при большой необходимости (например, требования хранения в БД символов других алфавитов) может быть изменена на UTF-8 или иную, при этом необходимо также скорректировать .properties файлы приложений биллинга на предмет кодировки БД.

Опции mysqld - общие параметры:
  • 'datadir' - каталог для хранения БД, лучше если это будет отдельный диск (RAID); высокие требования по надёжности и скорости.
  • 'tmpdir' - каталог для хранения временных файлов, лучше сделать отдельным быстрым диском; невысокие требования по надёжности, высокие по скорости; можно использовать RAM диск.
  • 'socket' - файловый сокет, возможность подключения консольным клиентом.
  • 'user' - пользователь ОС, под которым запускается БД.
  • 'log-slow-queries' - логирование запросов, выполняющихся длительное время.
  • 'skip-name-resolve' - отключает DNSрезолвинг для устанавливаемых соединений.
  • 'default-storage-engine' - тип хранилища таблиц по-умолчанию, InnoDB - транзакционный тип хранилища.
  • 'default-character-set' - кодировка по-умолчанию для вновь создаваемых таблиц.
  • 'default-collation' - collation (порядок букв, используется при сортировке) по-умолчнию для вновь создаваемых таблиц.
  • 'sql-mode' - запрещается установка режимов 'STRICT_TRANS_TABLES' и 'STRICT_ALL_TABLES', это приведёт к неработоспособности некоторых компонентов биллинговой системы.
  • 'max_allowed_packet' - максимальный размер пакета с запросом, принимаемого сервером.
  • 'max_connections' - ограничение на максимальное число соединений с БД.
  • 'memlock' - запрет на перенос процесса mysqld в свап.
  • 'table_cache' - максимальное количество описаний структур открытых таблиц в кэше.
  • 'thread_cache_size' - размер кэша потоков для предотвращения их повторного создания.
  • 'thread_concurrency' - число одновременно работающих потоков, рекомендуется ставить 2 * 'количество CPU' + количество дисков.

Запрещается установка опции 'skip-networking', т.к. Java приложение подключается к серверу с использованием TCP протокола, а не через файловый сокет.

Опции mysqld - InnoDB:
  • 'innodb_file_per_table' - для возможности использования Backup базы с помощью snapshot'ов (Linux, LVM)в ОС LINUX.
  • 'innodb_log_group_home_dir' - путь к каталогу под журнал транзакций, лучше если это будет отдельный диск; высокие требования по скорости и надёжности, низкие по объёму.
  • 'innodb_buffer_pool_size' - размер буфера под все нужды, он должен составлять порядка 70-80 % от общей памяти сервера БД.
  • 'innodb_additional_mem_pool_size' - параметр можно не изменять, размер буфера под доп. цели.
  • 'innodb_log_files_in_group' - количество файлов журналов транзакций в группе журналов; InnoDB производит запись в файлы по круговому способу; увеличение ускоряет запись но тормозит восстановление информации в случае сбоя.
  • 'innodb_log_file_size' - размер каждого файла журнала в группе журналов (указывается в мегабайтах).
  • 'innodb_log_buffer_size' - размер буфера, который в InnoDB используется для записи информации файлов журналов на диск.
  • 'innodb_lock_wait_timeout' - время простоя (в секундах), на протяжении которого транзакция InnoDB может ожидать прекращения блокировки прежде, чем будет произведен откат.
  • 'innodb_thread_concurrency' - должно совпадать с 'thread_concurrency'; число одновременно работающих потоков, рекомендуется ставить 2 * 'количество CPU' + количество дисков.
  • 'innodb_flush_log_at_trx_commit' - 2 отменяет сброс данных на диск при каждой транзакции, ускорение работы.
  • 'innodb_flush_method' - O_DIRECT отключает двойную буферизацию (самим mysql и ОС).
Опции mysqld -MyIsam
  • 'key_buffer_size' - размер кэша для хранения индексов;
  • 'myisam_recover' -восстановление битых таблиц при старте сервера.
  • 'myisam_repair_threads' - число потоков восстановления.
  • 'myisam_data_pointer_size' - возможность создания больших первичных ключей в таблицах.
Опции mysqld - репликации, если используется
  • 'server-id' - идентификатор сервера.
  • 'log-bin' - место хранение bin-логов; лучше если это будет отдельный диск, высокие требования по скорости и надёжности, малые по объёму.
  • 'expire_logs_days' - автоматическое удаление старых bin-логов.
  • 'replicate-do-db' - реплицируемая БД.
  • 'relay-log-space-limit' - ограничение на объём bin-логов.
Опции mysqld_safe
  • 'open-files-limit' - лимит количества открытых файлов для ОС Linux.
  • 'log-error' - файл для логирования ошибок.
  • 'pid-file' - PID файл процесса.
Опции mysqldump
  • 'max_allowed_packet' - установка маскимально возможного размера пакета при снятии дампов утилитой mysqldump.
  • 'default-character-set' - кодировка по-умолчанию при снятии дампов БД.
Опции client
  • 'default-character-set' - кодировка по-умолчанию при подключении консольным клиентом.

Ссылки

Набор Perl утилит для работы с MySQL

В архиве mysql_perl_utilites.zipразмещены файлы:

  • 'access.pm' - параметры доступа к MySQL для остальных скриптов.
  • 'extract_myisam.pl' - выбор MyIsam таблиц из базы и вывод в файл 'tables'.
  • 'convert.pl' - конвертация таблиц из файла 'tables' в InnoDb.
  • 'drop.pl' - удаление таблиц, перечисленных в файле 'tables'.

Запросы

SET FOREIGN_KEY_CHECKS =0;
UPDATE tbl_user SET id =1WHERE id =133;
UPDATE tbl_form SET user_id =1WHERE user_id =133;
SET FOREIGN_KEY_CHECKS =1;
  • UPDATE tbl_table t SET t.title = 'YYY' WHERE t.id IN (SELECT id FROM tbl_table) - но так работать не будет, для таких обновлений нада использовать временную таблицу
UPDATE tbl_point p2
INNERJOIN tbl_point p1 ON p1.id = p2.id AND p1.location =''SET p2.location = POINTFROMTEXT(CONCAT('POINT(',p1.latitude,' ',p1.longitude,')'));

Исправление ошибок

MySAM

InnoDB

Оптимизация

<nspages -h1 -subns -exclude:start -textNS="Категории:" -textPages="Страницы:">

Обрабтка урл в Apache2 - [Вопрос / ответ]

$
0
0

Обрабтка урл в Apache2

mod_rewrite

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

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

Я предполагаю, что читатель уже знаком с тем, что такое mod_rewrite, и не буду описывать его основы, которые легко найти в интернете. Также нужно отметить, что в статье освещается работа mod_rewrite при использовании его директив в файле .htaccess. Отличия при работе в контексте <VirtualHost> изложены в конце статьи.

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

С чем работает RewriteRule

Первому RewriteRule передается путь от того места, где находится .htaccess, до запрошенного файла. Эта строка никогда не начинается со "/". Последующим RewriteRule передается результат предыдущих преобразований.

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

Когда только начинаешь работать с mod_rewrite, логично предполагаешь, что он работает со ссылками. Однако в случае с использованием mod_rewrite в .htaccess это не так. На самом деле в RewriteRule передается не ссылка, а путь до запрошенного файла.

Из-за внутренней архитектуры Apache в тот момент, когда в действие вступает .htaccess, mod_rewrite может оперировать только с путем до файла, который должен быть обработан. Это связано с тем, что до передачи в mod_rewrite запрос уже могли изменить другие модули (например, mod_alias), и итоговый путь до файла на сайте уже может не совпадать с исходной ссылкой. Если бы mod_rewrite работал с исходной ссылкой, он бы нарушал действие модулей, которые изменили запрос до него.

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

Так вот, именно этот путь, от которого отрезан путь до .htaccess, передается в первый RewriteRule. Например:

Запрос: http://example.com/templates/silver/images/logo.gif
DocumentRoot: /var/www/example.com
Путь до файла: /var/www/example.com/templates/silver/images/logo.gif
.htaccess находится в: /var/www/example.com/templates/.htaccess

В первый RewriteRule будет передано: silver/images/logo.gif Обратите внимание: «templates/» тоже отрезалось. как работает RewriteRule Путь до .htaccess отрезается вместе со слешем. Из этого есть следствие: строка, которая изначально передается на обработку RewriteRule никогда не начинается со "/".

Важно запомнить, что не делает RewriteRule. Она не обрабатывает имя сайта, аргументы, которые переданы в скрипт, да и ссылку обрабатывает не всю, если .htaccess размещен не в корне сайта. Всем этим занимается RewriteCond, которого кратко коснемся чуть позже. Итак:

# работать не будет - правило начинается со /
RewriteRule ^/index.php$ /my-index.php

# работать не будет - название сайта не анализируется RewriteRule
RewriteRule ^example.com/.* http://www.example.com

# работать не будет - аргументы ссылки не попадают в RewriteRule
RewriteRule index.php\?newspage=([0-9]+) news.php?page=$1

# Будет работать только если .htaccess находится там же, где находится папка templates,
# например, в корне сайта. То есть, если .htaccess находится в templates/.htaccess , правило
# работать НЕ БУДЕТ, потому что mod_rewrite отрежет путь до .htaccess и на вход RewriteRule
# строка попадет уже без "templates/"
RewriteRule ^templates/common/yandex-money.gif$ templates/shared/yad.gif

В начале использования mod_rewrite я рекомендую работать с ним только в .htaccess в корне сайта. Это несколько упростит контроль за его работой.

С чем работает RewriteRule, мы разобрались. Теперь посмотрим, как он работает.

Как работает RewriteRule

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

Как мы выяснили выше, на вход RewriteRule попадает путь от .htaccess до запрошенного файла. Удобнее всего теперь абстрагироваться от путей и ссылок и рассматривать то, с чем работает RewriteRule, как обычную строку. Эта строка передается от RewriteRule к RewriteRule, видоизменяясь, если какое-то из RewriteRule сработало.

В общем виде, если исключить сложности с использованием флагов (некоторые из которых мы рассмотрим ниже) и сложности с составлением регулярных выражений (которых мы почти не будем касаться в этой статье), RewriteRule работает ОЧЕНЬ просто. Взяли строку. Сравнили с регулярным выражением в первом аргументе. Если есть совпадение — заменили всю строку на значение второго аргумента. Передали строку следующему RewriteRule. Вот, в общем, и все. Чтобы наглядно проиллюстрировать, что RewriteRule работает именно со строкой, рассмотрим следующий фантастический пример:

# Запрос: http://mysite.com/info.html
# В первый RewriteRule попадет "info.html"

# Преобразовываем запрос в произвольную строку.
RewriteRule ^info.html$ "I saw a turtle in the hole. And it was dancing rock-n-roll. And it was smiling. All in all, it was a very funny doll."

# "info.html" -> "I saw a turtle..."

# Заменяем эту строку на внешнюю ссылку.
RewriteRule turtle https://example.com/information/index.html

# "I saw a turtle..." -> "https://example.com/information/index.html"

# Заменяем имя сайта!
RewriteRule ^(.*)example.com(.*)$ $1example.org$2

# "https://example.com/information/index.html" -> "https://example.org/information/index.html"

# Заменяем протокол!
RewriteRule ^https:(.*)$ ftp:$1

# "https://example.org/information/index.html" -> "ftp://example.org/information/index.html"

# Заменяем конечную ссылку.
RewriteRule ^(.*)/index.html$ $1/main.php

# "ftp://example.org/information/index.html" -> "ftp://example.org/information/main.php"

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

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

https://

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

После того как все преобразования произведены и выполнено последнее RewriteRule, вступает в силу RewriteBase.

Для чего нужен RewriteBase

Если получившийся после преобразований запрос является относительным и отличается от исходного, RewriteBase добавит себя к нему слева. Нужно обязательно указывать RewriteBase в .htaccess. Его значение — путь от корня сайта до .htaccess. RewriteBase выполняется только после всех RewriteRule, а не между ними.

Мы уже говорили выше о том, что в mod_rewrite, работающий в .htaccess, попадает абсолютный путь до запрошенного файла. Чтобы передать его в RewriteRule, mod_rewrite отрезает путь до .htaccess. Потом правила RewriteRule одно за одним последовательно изменяют запрос. И вот после того, как запрос изменен, Apache должен восстановить абсолютный путь до файла, который он должен в итоге обработать. RewriteBase фактически является хаком, который помогает восстановить исходный путь до файла.

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

После всех преобразований RewriteBase смотрит, относительный получился в итоге путь или абсолютный. В контексте Apache имеется в виду относительный или абсолютный путь, отсчитывая от корня сайта: images/logo.gif — относительный. /images/logo.gif — абсолютный (в начале слеш). http://example.com/images/logo.gif— самый абсолютный из всех. Если путь абсолютный, RewriteBase ничего не делает. А если относительный — RewriteBase дописывает себя слева. Это работает как для внутренних, так и для внешних редиректов:

# .htaccess находится в /images/
# RewriteBase указан /images/
RewriteBase /images/

# Запрос http://example.com/images/logo.gif
# На вход RewriteRule попадает "logo.gif"
RewriteRule ^logo.gif$ logo-orange.gif
# После RewriteRule: "logo.gif" -> "logo-orange.gif"
# После RewriteBase: "logo-orange.gif" -> "/images/logo-orange.gif"

# Запрос http://example.com/images/header.png
# На вход RewriteRule попадает "header.png"
RewriteRule ^header.png$ /templates/rebranding/header.png
# После RewriteRule: "header.png" -> "/templates/rebranding/header.png"
# После RewriteBase: ничего не меняется, так итоговый результат преобразований начинается со "/'.

# Запрос http://example.com/images/director.tiff
# На вход RewriteRule попадает "director.tiff"
# Используем внешний относительный редирект
RewriteRule ^director.tiff$ staff/manager/director.tiff [R=301]
# После RewriteRule: "director.tiff" -> "staff/manager/director.tiff"
# + mod_rewrite запомнил, что будет внешний редирект
# После RewriteBase: "staff/manager/director.tiff" -> "/images/staff/manager/director.tiff"
# mod_rewrite вспомнил про внешний редирект:
# "/images/staff/manager/director.tiff" -> http://example.com/images/staff/manager/director.tiff

Обычно после некоторого знакомства с mod_rewrite складывается следующая привычка:

  1. в каждый .htaccess добавлять «RewriteBase /»
  2. все перенаправления начинать со слеша: «RewriteRule news.php /index.php?act=news». Это помогает избавиться от артефактов работы RewriteBase, но так делать неправильно. Теперь, когда нам известно, что делает RewriteBase, можно сформулировать следующие корректные правила:

RewriteBase должен совпадать с путем от корня сайта до .htaccess. Начинать перенаправления со "/" нужно только тогда, когда необходимо указать абсолютный путь от корня сайта до файла.

Что будет, если не указать RewriteBase? По умолчанию Apache делает его равным абсолютному пути на файловой системе до .htaccess (например, /var/www/example.com/templates/). Некорректность такого предположения Apache проявляется на внешних относительных редиректах:

# Запрос http://example.com/index.php
# DocumentRoot: /var/www/example.com/
# .htaccess находится в корне сайта, и в нем НЕ УКАЗАН RewriteBase.
# Поэтому по умолчанию RewriteBase равен абсолютному пути до .htaccess: /var/www/example.com/

# На входе RewriteRule - "index.php"
RewriteRule ^index.php main.php [R]
# На выходе: "index.php" -> "main.php"
# mod_rewrite запомнил, что нужен внешний редирект

# Закончились RewriteRule
# mod_rewrite все равно выполняет RewriteBase, так как у него есть значение по умолчанию.
# Получается: "main.php" -> "/var/www/example.com/main.php"

# Здесь mod_rewrite вспоминает, что был внешний редирект:
# "/var/www/example.com/main.php" -> http://example.com/var/www/example.com/main.php

# Получилось совсем не то, что имели в виду.

Итак, запрос прошел через все RewriteRule, после чего к нему, в случае необходимости, добавился RewriteBase. Должен ли теперь Apache отдать файл, на который показывает результирующий путь? Нет. Теперь получившийся запрос будет обрабатываться еще раз.

Как работает mod_rewrite. Флаг [L]

mod_rewrite запускает обработку запроса снова и снова, до тех пор, пока он не перестанет меняться. И флаг [L]не может это остановить.

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

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

— Постойте, но ведь есть флаг [L], который останавливает обработку запроса mod_rewrite'ом!

Не совсем так. Флаг [L]останавливает текущую итерацию обработки запроса. Однако если запрос был изменен теми RewriteRule, которые все-таки успели отработать, Apache запустит цикл обработки запроса заново с первого RewriteRule.

# Запрос: http://example.com/a.html

RewriteBase /

RewriteRule ^a.html$ b.html [L]
RewriteRule ^b.html$ a.html [L]

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

Чтобы избежать подобных ситуаций, рекомендуется использовать флаг [L] только при необходимости. Необходимость может быть двух типов: Когда используется внешний редирект — [L,R=301] или [L,R=302]. В случае внешнего редиректа дальнейшая обработка запроса нежелательна (см. ниже про флаг [R]), и ее лучше остановить. Когда в .htaccess есть зацикливание, от которого не избавиться, и обработку запроса mod_rewrite'ом нужно принудительно прекратить. В этом случае используется специальная конструкция — см. в конце статьи советы на эту тему.

А вот приведенный ниже пример зацикливаться не будет. Попробуйте определить, почему, и какой в итоге файл будет отдан Apache'м.

# Запрос: http://example.com/a.html
# Начало .htaccess

RewriteBase /
RewriteRule ^a.html$ b.html
RewriteRule ^b.html$ a.html

# Конец .htaccess

Отгадка: В результате выполнения всех RewriteRule запрос меняется таким образом, что конечный результат равен исходному. Apache видит это и не запускает повторную обработку запроса. Будет возвращен файл a.html.

Как работает mod_rewrite. Флаг [R]

  • Флаг [R]не останавливает обработку запроса, возвращая сразу внешний редирект. Вместо этого он запоминает необходимость внешнего редиректа, и обработка запроса продолжается следующими RewriteRule. Рекомендуется всегда использовать с флагом [L].
  • Флаг [R]сообщает Apache, что нужно выполнить не внутренний, а внешний редирект. Чем отличается внешний редирект от внутреннего? Внутренний редирект просто изменяет путь до файла, который будет отдан пользователю, при этом пользователь считает, что получает тот файл, который он изначально запросил. При внешнем же редиректе Apache вместо содержимого файла возвращает пользователю статус ответа 301 или 302 и сообщает ссылку, по которой браузер должен обратиться для получения файла.

Казалось бы, при обработке флага [R] Apache должен сразу прекратить обработку RewriteRule и вернуть пользователю внешний редирект. Однако давайте вспомним фантастический пример из раздела «Как работает RewriteRule». В нем мы сначала указали флаг [R], обозначив необходимость внешнего редиректа, после чего продолжили изменять ссылку следующими RewriteRule.

Именно так и работает Apache при указании внешнего редиректа. Он просто «помечает» себе, что после выполнения всех правил необходимо вернуть статус 302 (по умолчанию), но при этом продолжает выполнение всех RewriteRule дальше по списку. Мы можем и дальше изменять запрос как нам нужно, единственное, что не получится — сделать редирект обратно внутренним.

Тем не менее, вряд ли вы хотите после отдачи внешнего редиректа каким-либо образом изменять его. Поэтому рекомендуется при употреблении флага [R]указывать его совместно с [L]:

# BlackJack переехал на красивое имя
RewriteRule ^bj/(.*) blackjack/$1 [R=301,L]

# Можно использовать просто внешнюю ссылку
RewriteRule ^bj/(.*) http://blackjack.example.com/$1 [L]

Вместо использования флага [R]можно указывать просто внешнюю ссылку. В этом случае Apache сам догадается, что необходимо сделать внешний редирект. Здесь, как и с в случае с явным указанием флага [R], рекомендуется использовать флаг [L]. Если внешний редирект ведет на тот же сайт, лучше использовать флаг [R]без указания полной ссылки (иными словами, использовать относительный внешний редирект). Это сделает правило независимым от имени сайта. Если же внешний редирект ведет на другой сайт, иначе, как указав полную внешнюю ссылку, это сделать не получится.

Как работает mod_rewrite. Указание параметров запроса и флаг [QSA]

Изменение параметров запроса в RewriteRule не изменяет строку, с которой работает следующий RewriteRule. Однако при изменении параметров изменяется переменная %{QUERY_STRING}, с которой может работать RewriteCond.

Используемая терминология: «параметры» — параметры запроса, «аргументы» — аргументы RewriteRule.

С помощью RewriteRule можно изменять не только путь до файла, который будет обрабатываться, но и параметры запроса GET, которые будут ему передаваться. Это часто используется для передачи обработки ЧПУ в общий скрипт-обработчик, например: RewriteBase /

# Запрос: http://example.com/news/2010/07/12/grand-opening.html
# На входе: "news/2010/07/12/grand-opening.html"
RewriteRule ^news/(.*)$ index.php?act=news&what=$1
# После RewriteRule: "news/2010/07/12/grand-opening.html" -> "index.php"
# %{QUERY_STRING}: "" -> "act=news&what=2010/07/12/grand-opening.html"

В момент, когда правило RewriteRule встречает вопросительный знак во втором аргументе, оно понимает, что происходит изменение параметров в запросе. В результате происходит следующее: RewriteRule заменяет строку, с которой оно работает, на часть второго аргумента до вопросительного знака. Обратите внимание, что новые параметры запроса не попадают в строку, с которой будут работать последующие правила RewriteRule. Часть второго аргумента после вопросительного знака попадает в переменную %{QUERY_STRING}. Если был указан флаг [QSA], параметры запроса будут добавлены в начало %{QUERY_STRING}. Если флаг указан не был, %{QUERY_STRING} полностью заменится параметрами запроса из RewriteRule. Еще пара примеров:

RewriteBase /

# Запрос: http://example.com/news/2010/?page=2
# На входе RewriteRule: "news/2010/"
RewriteRule ^news/(.*)$ index.php?act=news&what=$1
# После преобразования: "news/2010/" -> "index.php"
# Значение %{QUERY_STRING}: "page=2" -> "act=news&what=2010/"

Скорее всего, правило выше работает неправильно, так как теряется аргумент page. Исправим это:
RewriteBase /

# Запрос: http://example.com/news/2010/?page=2
# На входе RewriteRule: "news/2010/"
RewriteRule ^news/(.*)$ index.php?act=news&what=$1 [QSA]
# После преобразования: "news/2010/" -> "index.php"
# Значение %{QUERY_STRING}: "page=2" -> "act=news&what=2010/&page=2"

Мы добавили только флаг [QSA], и правило стало работать корректно.

Важно понимать, что изменение параметров запроса изменяет %{QUERY_STRING}, который может использоваться в дальнейшем в RewriteCond. Это нужно учитывать при составлении последующих правил, проверяющих аргументы.

— Конечно, изменяется, ведь запрос уходит на повторную обработку Apache'м!

Нет, %{QUERY_STRING} изменяется сразу же. Доказательство приводить не буду — про параметры и так уже написано больше, чем интересно читать :)

Что же делать, чтобы проверить в RewriteCond именно те параметры запроса, которые передал пользователь, а не модифицированные RewriteRule'ами? Смотрите советы в конце статьи.

RewriteCond и производительность

Сначала проверяется совпадение запроса с RewriteRule, а уже потом — дополнительные условия RewriteCond.

Пару слов стоит сказать о том, в каком порядке mod_rewrite выполняет директивы. Так как в .htaccess сначала идут RewriteCond, а потом RewriteRule, кажется, что mod_rewrite сначала проверяет все условия, а потом приступает к выполнению RewriteRule.

На самом деле все происходит наоборот. Сначала mod_rewrite проверяет, подходит ли текущее значение запроса под регулярное выражение RewriteRule, а уже потом будет проверять все условия, перечисленные в RewriteCond.

Так что если у вас в RewriteRule регулярное выражение на две страницы и вы, задумавшись о производительности, решили ограничить выполнение этого правила дополнительными RewriteCond, знайте — ничего не получится. В этом случае лучше использовать флаги RewriteRule [C] или [S], чтобы пропустить более сложное правило, если более простые проверки не сработали.

Переменные и флаги RewriteCond, остальные флаги RewriteRule и прочее

Читайте документацию.

Мы познакомились с принципами работы RewriteRule, RewriteBase, флагов [L], [R]и [QSA], а также разобрали механизм обработки запросов внутри mod_rewrite. Из незатронутого остались: другие флаги RewriteRule, директивы RewriteCond и RewriteMap.

К счастью, эти директивы и флаги не таят в себе каких-либо загадок и работают именно так, как описано в большинстве учебников. Для их понимания достаточно почитать официальную документацию. В первую очередь рекомендую изучить список переменных, которые можно проверять в RewriteCond — %{QUERY_STING}, %{THE_REQUEST}, %{REMOTE_ADDR}, %{HTTP_HOST}, %{HTTP:header} и т. д.)

Разница в работе mod_rewrite в контексте .htaccess и в контексте VirtualHost

В контексте <VirtualHost> mod_rewrite работает с точностью до наоборот.

Как я говорил в начале статьи, все описанное выше касается применения mod_rewrite в контексте .htaccess. Если же mod_rewrite используется в <VirtualHost>, он будет работать по-другому: В <VirtualHost> в RewriteRule попадает весь путь запроса, начиная от первого слеша, заканчивая началом параметров GET: «http://example.com/some/news/category/post.html?comments_page=3» → "/news/category/post.html". Эта строка всегда начинается со /. Второй аргумент RewriteRule также необходимо начинать со /, иначе будет «Bad Request». RewriteBase не имеет смысла. Проход правил происходит только один раз. Флаг [L]действительно заканчивает обработку всех правил, описанных в <VirtualHost>, без каких-либо последующих итераций.

Советы и решения

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

Составление регулярных выражений

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

# Начинайте все регулярные выражения с "^" (признак начала строки)
# и заканчивайте "$" (признак конца строки):
RewriteRule ^news.php$ index.php
# Даже если в этом нет необходимости - для универсальности и лучшего понимания конфигурации:
RewriteRule ^news/(.*)$ index.php

# Если под маску должны попадать только цифры - укажите это явно.
# Если какие-то цифры постоянны, укажите их явно.
# Если в оставшейся части запроса не могут присутствовать слеши, ограничьте их присутствие.
# Не забывайте экранировать "." (точки).
# Следующее правило нацелено на запросы вида http://example.com/news/2009/07/28/b-effect.html
RewriteRule ^news/20[0-9]{2}/[0-9]{2}/[0-9]{2}/[^/]+\.html index.php

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

Изменение внешних редиректов

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

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

Как остановить бесконечный цикл

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

На сайте была страница /info.html. Специалист по SEO решил, что поисковые системы будут лучше индексировать эту страницу, если она будет называться /information.html и попросил сделать внешний редирект с info.html на information.html. Однако разработчик сайта по каким-то своим соображениям не может просто переименовать info.html в information.html и сделать редирект — ему нужно, чтобы данные обязательно отдавались непосредственно из файла info.html. Он пишет следующее правило: # сделать внешний редирект RewriteRule ^info.html information.html [R,L] # но по запросу /information.html все равно отдать info.html RewriteRule ^information.html info.html

… и сталкивается с бесконечным циклом. Каждый запрос /information.html получает внешний редирект снова на /information.html.

Решить эту проблему можно как минимум двумя способами. На Хабре был уже описан один из них — нужно установить переменную окружения и на основании ее значения прекращать перенаправления. Код будет выглядеть следующим образом:

RewriteCond %{ENV:REDIRECT_FINISH} !^$
RewriteRule ^ - [L]

RewriteRule ^info.html$ information.html [R,L]
RewriteRule ^information.html$ info.html [E=FINISH:1]

Обратите внимание, что к имени переменной mod_rewrite добавляет 'REDIRECT_'.

Второй способ — проверить в THE_REQUEST, что именно было запрошено пользователем:

# Внешний редирект происходит только если пользователь запросил info.html.
# Если же info.html - это результат внутреннего перенаправления, правило срабатывать не будет.
RewriteCond %{THE_REQUEST} "^(GET|POST|HEAD) /info.html HTTP/[0-9.]+$"
RewriteRule ^info.html$ information.html [R,L]

RewriteRule ^information.html$ info.html

Анализ исходного запроса пользователя — борьба с раскрытием ссылок Apache

При обработке запроса Apache раскрывает закодированные (URL-encoded) символы из первоначального запроса. В некоторых случаях это может быть нежелательно — разработчик хочет проверять именно первоначальный, немодифицированный запрос пользователя. Сделать это можно, проверяя в RewriteCond переменную %{THE_REQUEST}:

RewriteCond %{THE_REQUEST} ^GET[\ ]+/tag/([^/]+)/[\ ]+HTTP.*$
RewriteRule ^(.*)$ index.php?tag=%1 [L]

Rewrite

Директива RewriteRule Директива RewriteRule устанавливает правила перехода. Синтаксис следующий:

RewriteRule Шаблон Подстановка [коды]

Директива RewriteCond Директива RewriteCond определяет условия при котором выполняется правила в RewriteRule.

RewriteCond Сравниваемая_Строка Условие

Например, этими условиями могут быть браузер пользователя, IP-адрес, заголовок и т.д.

Директива RedirectMatch Директива RedirectMatch в htaccess аналогична Redirect с той лишь разницей, что позволяет записывать регулярные выражения.

RedirectMatch [status] Откуда Куда

Вопрос / ответ

Примеры настройки 301 редиректов в htaccess

Options +FollowSymLinks
RewriteEngine On

Комментарий в файле htaccess обозначается символом решётка «#» в начале строки # Текстовый комментарий, данная строчка не будет обрабатываться. 301-редирект с домена без WWW на домен с WWW префиксом

RewriteCond % ^site\.ru$ [NC]
RewriteRule ^(.*)$ http://www.site.ru/$1 [R=301,L]

С домена с WWW префиксом на без

RewriteCond % ^www.site\.ru$ [NC]
RewriteRule ^(.*)$ http://site.ru/$1 [R=301,L]

Для HTTPS-версии:

RewriteCond % ^80$ [OR]
RewriteCond % =on
RewriteRule ^(.*)$ https://site.ru/$1 [R=301,L]

Стандартный 301-редирект с одной статической страницы на другую Redirect 301 /was.php http://www.site.ru/new.phpПри этом в файле htaccess, новый адрес указывать необходимо полностью с http и доменным именем. В ряде случаев полезен редирект через RewriteRule

RewriteRule ^dir /dir-new/$1 [R=301,L]

Настройка 301-редирект для страницы с GET параметрами Скажем, адрес страницы имеет вид: http://www.htaccess.ru/dir/index.php?IBLOCK_ID=1&SECTION_ID=111тогда в htaccess для настройки 301 редиректа на новый адрес, необходимо использовать следующее правило:

RewriteCond % ^IBLOCK_ID=1&SECTION_ID=111$ [NC]
RewriteRule ^dir/index\.php$ /new/sef/? [R=301,L]

Если один (или несколько) из GET параметров не задан(ы) или может иметь произвольное значение (в нашем примере это SECTION_ID), можно использовать следующий код:

RewriteCond % ^IBLOCK_ID=1&SECTION_ID=(.*)$ [NC]
RewriteRule ^dir/index\.php$ /new/sef/? [R=301,L]

Убираем все GET-параметры после знака вопроса (?) Располагать после: RewriteBase /

301-редирект со страницы без заданного параметра в корень Если адрес имеет следующий вид: http://www.htaccess.ru/?abcто для редиректа подойдет последовательность строчек:

RewriteCond % ^abc$ [NC]
RewriteRule ^$ /? [R=301,L]

301-редирект для конкретного файла, а не целой папки RewriteRule ^dir/$ http://www.htaccess.ru/new-dir/ [R=301,L]

Как быть с доменами в зоне РФ? 301-редирект с домена на домен

RewriteCond % ^old-site\.ru$ [NC]
RewriteRule ^(.*)$ http://www.site.ru/$1 [R=301,L]

И для домена в зоне РФ:

RewriteCond % ^xn-. \.xn--p1ai$ [NC]
RewriteRule ^(.*)$ http://www.site.ru/$1 [R=301,L]

Настройка редиректа на папки со слешем в конце / Настройка редиректа на папки без слеша (убираем слеш в конце) 301-редирект с домена на папку на другом домене

RewriteCond % ^si-te\.ru$ [NC]
RewriteRule ^(.*)$ http://www.site.ru/si-te/ [R=301,L]

Редирект со всех файлов домена, кроме папки администратора bitrix

RewriteRule ^bitrix/ /bitrix/admin/ [L,R=301]
RewriteRule ^(.*)$ http://www.newsite.ru/new/ [L,R=301]

Редирект всех файлов в папке на заданный файл

RewriteRule ^dir(.*)$ /new-file.php [L,R=301]

Редирект файлов из заданной папки кроме, определенного файла

RewriteRule ^dir/no-file.html /no-file-new.html [L,R=301]
RewriteRule ^dir(.*)$ /all.php [L,R=301]

Смена страниц с html расширения на php расширение

RedirectMatch 301 (.*)\.html$ http://www.new-site.ru$1.php

Перенос картинок / изображений из папки /img/ на поддомен

RewriteRule ^img/(.+)\.jpg$ http://img.domain.ru/$1.jpg [R=301,L]

Задание типа индексной страницы (php, html, htm и другие) Указывается порядок загрузки типов индексного файла, лежащих в корне каталога.

DirectoryIndex index.html index.php index.htm index.shtml

Редирект с индексной страницы php на саму папку (корень)

RewriteCond % ^[A-Z]<3,9>\ /index\.php\ HTTP/
RewriteRule ^index\.php$ http://www.site.ru/ [R=301,L]

Для всех индексных страниц на сайте:

RewriteRule ^(.*)index\.php$ http://www.site.ru/$1 [R=301,L]

Редирект с поддомена на основной домен второго уровня

RewriteCond % ^test.site.ru$ [NC]
RewriteRule ^(.*)$ http://site.ru% [R=301,NC,L,QSA]

Редирект для заданного файла в различных директориях (папках)

RewriteRule [^abc]/unique-file.html /unique-file.html [R=301,L]

Код позволяет поставить 301-редирект со всех папок вида http://htaccess.ru/***/uniqe-file.html на один файл в корне /unique-file.html. Бывает полезен при переделке сайта и изменении ссылок.

RewriteRule ^testovyi/test/?$ /studio/news/detail.php?ID=230354&PAGEN_2=11 [NC,L]

Код позволяет создать копию страницы с относительным адресом /studio/news/detail.php?ID=230354&PAGEN_2=11 по адресу /testovyi/test/

301-редирект с HTTPS-версии на HTTP Позволяет устранить наличие дублей URLс HTTPS в индексе поисковых систем.

Перенос сайта на версию с HTTPS (для всех страниц)

RewriteCond % ^80$ [OR]
RewriteCond % =on
RewriteRule ^(.*)$ https://htaccess.ru/$1 [R=301,L]

Настройка 403 кода ответа сервера для реф-спама (301-редирект для спама по REFERER) для списка ресурсов Настройка позволяет отклонить спамный реферальный трафик с ряда ресурсов по заголовку HTTP_REFERER.

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

ErrorDocument 404 /404-for-me.php

! Для сайтов, на которых используется не сервер Apache, аналогичные 301-редиректы легко настраиваются с помощью PHP.

header(«HTTP/1.1 301 Moved Permanently»);
header(«Location: http://www.htaccess.ru/dir/»);
exit();
?>

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

Если требуется настроить редирект только для некоторых USER_AGENT’ов, а не для всех пользователей

RewriteCond % (iPad|ipad|iphone|iPhone|ipod|iPod|android|midp|j2me|symbian|series\ 60|symbos|windows\ mobile|windows\ ce|ppc|smartphone|blackberry|mtk|bada|windows\ phone) [NC]
RewriteRule (.*) http://mobile.htaccess.ru/ [L,R=301]

Если требуется настроить редирект для всех поисковых роботов (представлен список их USER_AGENT’ов)

RewriteCond % !(accoona|ia_archiver|antabot|ask\ jeeves|baidu|dcpbot |eltaindexer|feedfetcher|gamespy|gigabot|googlebot |gsa-crawler|grub-client|gulper|slurp|mihalism|msnbot|worldindexer |ooyyo|pagebull|scooter|w3c_validator|jigsaw|webalta|yahoofeedseeker |yahoo!\ slurp|mmcrawler|yandexbot|yandeximages |yandexvideo|yandexmedia|yandexblogs|yandexaddurl|yandexfavicons |yandexdirect|yandexmetrika|yandexcatalog|yandexnews |yandeximageresizer) [NC]
RewriteRule (.*) http://no-search.site.ru/ [L,R=301]

Несколько простых редиректов Редирект с www.htaccess.ru/component/content/?view=featuredна www.htaccess.ru/

RewriteCond % ^view=featured$ [NC]
RewriteRule ^component/content/$ /? [R=301,L]

Редирект с www.htaccess.ru/index.php?idc=4&marea=6на www.htaccess.ru/

RewriteCond % ^idc=4&marea=6$ [NC]
RewriteRule ^index\.php$ /? [R=301,L]

Синтаксис для регулярных выражений файла htaccess

  • . — Точка заменяет произвольный символ.
  • [abc] — обозначает перечень символов, совпадающих с буквами a, b, или с.
  • [^abc] — перечень символов, которые не входят в указанных диапазон. Совпадёт с любым символом, кроме a, b, или с.
  • * — означает, что предшествующий символ может повторяться (0 или более раз).
  • [abc]* — команда найдёт идущие подряд символы из заданного набора.
  • [^abc]* — с точностью до наоборот.
  • .* — заменяет абсолютно любой набор символов. “.*” — найдёт все подстроки между кавычками.
  • ^ — начало строки (в том случае, если используется в начале выражения).
  • $ — обозначает конец строки.
  • \w — буква, цифра или подчёркивание _.
  • \d — заменяет любую цифру.
  • \D — заменяет любой символ, но не цифру.
  • 9 — заменяет любую цифру.
  • [a-z] — любая буква от a до z (весь латинский набор символов) в нижнем регистре.
  • [A-Z] — любая буква от A до Z в ВЕРХНЕМ регистре.
  • [a-zA-Z] — любая буква от a до Z в любом регистре.
  • [a-Z] — то же самое.

❓Как сделать 301 редирект папки Сделать переадресацию папки необходимо в нескольких случаях – если вы перемещаете её в пределах сайта для сокращения url и оптимизации структуры, а также для редиректа 301 folder на поддомен. Два этих варианта я и рассмотрю.

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

И нужно, чтобы она открывалась по адресу:

При этом важно сохранить урл, изменив только папку корня, то есть, все страницы за folder-storage-directory должны открываться после folder-shipping.

Проще говоря, есть адрес:

А надо чтобы она открывалась по адресу:

Поможет в этом код:

В результате адрес сокращается и структура сайта более понятна ботам. Также плюшка оптимизации.

Редирект папки на поддомен Иногда требуется переадресация папки на поддомен. Такая неприхотливая нужда возникает, если надо сделать 301 не всего сайта, а только одной (двух, трёх) папки. Например, тематика вашего основного сайта слишком распылилась, и вы хотите разбросать её по поддоменам, собрав на каждом из них материалы одной темы.

Предположим, есть папка:

И надо сделать редирект 301 на:

Поможет в этом код в htaccess:

RewriteRule ^ru/(.*)$ http://ru.site.ru/$1 [R=301,L]

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

Для использования кодов просто замените в нём домен и папки на свои директории и вставьте в htaccess. Делаете редирект с одинаковым успехом на Joomla и других движках.

Источник

.htaccess При изменении файла новый набор настроек сразу начинает работать и не требует перезагрузки web-сервера.

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

Директива должна иметь вид:

Options Indexes FollowSymLinks
AllowOverride All
Require all granted

/var/www/ по необходимости нужно заменить на свою директорию сайта.

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

Если вывод будет Syntax OK, то выполните: service httpd restart.

Провайдеры по умолчанию включают эту настройку для папок с сайтами пользователей на виртуальном хостинге, а владельцам VPS/VDS и выделенных серверов нужно самостоятельно проверить у себя наличие такой конфигурации в Apache.

Каждая строка файла означает определенную команду конфигурации (директиву) Apache.

Пустые строки игнорируются.

Для этого нажмите правой кнопкой мыши на файл, чтобы открыть контекстное меню с пунктом “Просмотр/Правка”.

Filezilla использует для редактирования текстовый редактор Notepad++, который должен быть установлен на локальный компьютер.

В случае, если файла в папке сайта нет, создайте его самостоятельно.

Ниже будут рассмотрены наиболее востребованные из настроек в контексте web-хостинга.

Механизм перенаправления (редиректа) запросов Затем следует перечень специальных команд для настройки перенаправления, в зависимости от конкретных условий.

В своей работе механизм перенаправления mod_rewrite применяет специальную технологию программирования regexp для сравнения запросов с определенным шаблоном.

Склейка разных адресов одного сайта

RewriteEngine On
RewriteCond % ^www.mysite\.ru$ [NC]
RewriteRule ^(.*)$ http://mysite.ru/$1 [R=301,L]

1. Указание основного зеркала Предназначен для того, чтобы преобразовать домен с www на URLбез www. Достаточно ввести правило:

RewriteEngine On # включает работу
RewriteCond %{HTTP_HOST} ^www.название_вашего_сайта\ru$ [NC] #условия для начала перенаправления
RewriteRule ^( *)$ http://название_вашего_сайта_/$1 [R=301,L] #правило преобразования

2. Перенос на https На сегодняшний день поисковик Google активно призывает владельцев сайтов к использованию безопасного соединения, для чего необходимо перенаправлять пользователей с http на https при помощи кода:

RewriteEngine On
RewriteCond %(HTTPS) !on
RewriteRule (.*) https://%(HTTP_HOST)%(REQUEST_URL)

3. Проставление слеша в конце адреса Если вы не хотите, чтобы URLстраницы заканчивался названием каталога http:название_вашего_сайта.ru/catalog, введите в файл код: <code>RewriteCond %{REQUEST_URI} /+[^\.]+$ RewriteRule ^(.+[^/])$ %{REQUEST_URI}/ [R=301,L]</code> Выполнив данную команду, в дальнейшем после адреса в автоматическом режиме будет добавляться слеш: http:название_вашего_сайта.ru/catalog/

4. Перенос домена Изменив название сайта, не забудьте в .htaccess указать:

RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.yoursite.ru\.ru$ [NC]
RewriteRule ^(.*)$ http://www.your-site.ru/$1 [R=301,L]

Оптимизируя сайт и под Яндекс, и под Google, изменение доменного имени может быть чревато неприятными последствиями. Инструкции в robots.txt, предназначенные для Яндекса, перекрываются 301-редиректом. Но этого можно не допустить, добавив в код правило:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} robots.txt$ [NC]
RewriteRule ^([^/]+) $1 [L]
RewriteCond %{HTTP_HOST} ^mysite\.ru
RewriteRule ^(.*)$ http://www.my-site.ru/$1 [R=301,L]

5. Запретные команды для поискового бота В .htaccess, так же, как и в robots.txt, можно закрыть доступ к сайту для роботов поисковых систем:

RewriteEngine on
RewriteCond %{USER_AGENT} Googlebot
RewriteRule .* - [F] # F – выдает ошибку 403 – запрещено для сканирования

6. Редирект с одного сайта на другой

RewriteEngine On
RewriteCond %{HTTP_HOST} domain1.ua
RewriteRule (.*) http://domain2.ua/$1 [R=301,L]

Редирект с www на без www

Options +FollowSymLinks
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.*) [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]

Или более понятный синтаксис

Options +FollowSymLinks
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.domain\.com$ [NC]
RewriteRule ^(.*)$ http://domain.com/$1 [R=301,L]

smtp-client.pl - Консольный клиент для отправки почты - [Установка]

$
0
0

smtp-client.pl - Консольный клиент для отправки почты

Тест SMTP

smtp-cli is a powerful SMTP command line client with a support for advanced features, such as STARTTLS, SMTP-AUTH, or IPv6 and with a scriptable message composition capabilities supporting anything from simple plain-text messages right up to building complex HTML emails with alternative plain-text part, attachments and inline images. The MIME-Type of the attachments can either be guessed automatically or alternatively set on the command line, separately for each attachment if required.

http://www.logix.cz/michal/devel/smtp-cli/

Установка

$ apt-get install libio-socket-ssl-perl  libdigest-hmac-perl  libterm-readkey-perl libmime-lite-perl libfile-libmagic-perl libio-socket-inet6-perl
$ cd ~
$ wget http://www.logix.cz/michal/devel/smtp-cli/smtp-cli-3.6
$ mv smtp-cli-3.6 smtp-client.pl
$ cpan install YAML File::Type File::LibMagic IO::Socket::INET6 MIME::Lite Digest::HMAC_MD5 File::Type Term::ReadKey IO::Socket::SSL Net::DNS

Проверка

perl smtp-client.pl --verbose --host=localhost  

Отправка письма

$ perl smtp-client.pl --server=localhost --from noreplay@myhost.ru --to=test@yandex.ru --subject='Blah blah'--ipv4
$ perl smtp-client.pl --server=smtp.host.ru --from noreplay@myhost.ru --to=test@yandex.ru --subject='Blah blah'
$ perl smtp-client.pl --server=smtp.gmail.com --port=465--user=login--pass=888888
$ perl smtp-client.pl --subject='Blah'--body-plain='Message txt'
$ perl smtp-client.pl --subject='Blah'--body-html='Message txt'
$ perl smtp-client.pl --verbose--server='localhost'--from='noreply@my-server.ru'--to='my-email@yandex.ru'--subject='From SMTP'--body-plain='From SMTP'--ipv4

Параметры

        --server=<hostname>[:<port>]
                                Host name or IP address of the SMTP server.
                                May include the port after colon, alternatively
                                use --port.
        --port=<number>         Port where the SMTP server is listening.
                                (default: 25)

        -4 or --ipv4            Use standard IP (IPv4) protocol.
        -6 or --ipv6            Use IPv6 protocol. For hosts that have
                                both IPv6 and IPv4 addresses the IPv6
                                connection is tried first.

        --hello-host=<string>   String to use in the EHLO/HELO command.
        --disable-ehlo          Don't use ESMTP EHLO command, only HELO.
        --force-ehlo            Use EHLO even if server doesn't say ESMTP.

        Transport encryption (TLS)
        --disable-starttls      Don't use encryption even if the remote
                                host offers it.
        --ssl                   Start in SMTP/SSL mode (aka SSMTP).
                                Default when --port=465
        --disable-ssl           Don't start SSMTP even if --port=465
        --ssl-ca-file=<filename>
                                Verify the server's SSL certificate against
                                a trusted CA root certificate file.
        --ssl-ca-path=<dirname> Similar to --ssl-ca-file but will look for
                                the appropriate root certificate file in
                                the given directory. The certificates must
                                must be stored one per file with hash-links
                                generated by, for example, c_rehash script
                                from OpenSSL.

        Authentication options (AUTH)
        --user=<username>       Username for SMTP authentication.
        --pass=<password>       Corresponding password.
        --auth-login            Enable only AUTH LOGIN method.
        --auth-plain            Enable only AUTH PLAIN method.
        --auth-cram-md5         Enable only AUTH CRAM-MD5 method.
        --auth                  Enable all supported methods. This is
                                normally not needed, --user enables
                                everything as well.

        Sender / recipient
        --from=\"Display Name <add\@re.ss>\"
                                Sender's name address (or address only).
        --to=\"Display Name <add\@re.ss>\"
        --cc=\"Display Name <add\@re.ss>\"
        --bcc=\"Display Name <add\@re.ss>\"
                                Message recipients. Each parameter can be
                                used multiple times.
                                The --bcc addresses won't apprear in
                                the composed message.

        SMTP Envelope sender / recipient
        (rarely needed, use --from, --to, --cc and --bcc instead)
        --mail-from=<address>   Address to use in MAIL FROM command.
                                Use --from instead, unless you want
                                a different address in the envelope and
                                in the headers.
        --rcpt-to=<address>     Address to use in RCPT TO command. Can be
                                used multiple times. Normally not needed,
                                use --to, --cc and --bcc instead.
                                If set the --to, --cc and --bcc will only
                                be used for composing the message body and
                                not for delivering the messages.

        Send a complete RFC822-compliant email message:
        --data=<filename>       Name of file to send after DATA command.
                                With \"--data=-\" the script will read
                                standard input (useful e.g. for pipes).

        Alternatively build email a message from provided components:
        --subject=<subject>     Subject of the message
        --body-plain=<text|filename>
        --body-html=<text|filename>
                                Plaintext and/or HTML body of the message
                                If both are provided the message is sent
                                as multipart.
        --charset=<charset>     Character set used for Subject and Body,
                                for example UTF-8, ISO-8859-2, KOI8-R, etc.
        --text-encoding=<encoding>
                                Enforce Content-Transfer-Encoding for text
                                parts of the email, including body and
                                attachments. Must be one of:
                                ".join(", ", @valid_encodings)."
                                The default is: quoted-printable
        --attach=<filename>[\@<MIME/Type>]
                                Attach a given filename.
                                MIME-Type of the attachment is guessed
                                by default guessed but can optionally
                                be specified after '\@' delimiter.
                                For instance: --attach mail.log\@text/plain
                                Parameter can be used multiple times.
        --attach-inline=<filename>[\@<MIME/Type>]
                                Attach a given filename (typically a picture)
                                as a 'related' part to the above 'body-html'.
                                Refer to these pictures as <img src='cid:filename'>
                                in the 'body-html' contents.
                                See --attach for details about MIME-Type.
                                Can be used multiple times.
        --add-header=\"Header: value\"
        --replace-header=\"Header: value\"
        --remove-header=\"Header\"
                                Add, Replace or Remove pretty much any header
                                in the email. For example to set a different
                                Mailer use --replace-header=\"X-Mailer: Blah\",
                                to remove it altogether --remove-header=X-Mailer
                                or to add a completely custom header use
                                --add-header=\"X-Something: foo bar\".
        --print-only            Dump the composed MIME message to standard
                                output. This is useful mainly for debugging
                                or in the case you need to run the message
                                through some filter before sending.

        Other options
        --verbose[=<number>] | -v    Be more verbose, print the SMTP session.
        --missing-modules-ok    Don't complain about missing optional modules.
        --version               Print: smtp-cli version $version
        --help                  Guess what is this option for ;-)

Ошибки

Connect failed: IO::Socket::INET6: connect: timeout

Даж при наличии явного флага -4 или --ipv4 при отсутствии соеденения будет выдаваться эта ошибка

Connect failed: IO::Socket::INET6: connect: Connection refused

Данное сообщение выводится при невозможности установить соеденение с указанным IP в --server

dpkg - Пакетный менеджер - [Удаление группы пакетов по признаку в названии.]

$
0
0

dpkg - Пакетный менеджер

Продолжение настройки пакетов

$ dpkg--configure-a

Переустановка пакетов / Восстановдение пакетов

Исправить ошибки

Список установленных пакетов

dpkg --get-selections

Список установленных PHP 7.0

$ dpkg--get-selections|grep-v"deinstall"|grep php7.0|cut-f1

в строчку

$ dpkg--get-selections|grep-v"deinstall"|grep php7.0|cut-f1|tr'\n'' '

Поиск пакета, которому принадлежит конкретный файл.

Иногда не понятно какому пакету принадлежит данный файл в системе. Будь то исполняемый файл, библиотека и тп.

Для этого существует команда dpkg -S чего_ищем, но здесь есть маленькая хитрость:

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

  $ which ssh
  
  /usr/bin/ssh
  
  $ dpkg -S /usr/bin/ssh
  
  openssh-client: /usr/bin/ssh

или проще:

  $ dpkg -S `which ssh`
openssh-client: /usr/bin/ssh

Здесь видно что программа ssh входит в пакет openssh-client.

Удаление группы пакетов по признаку в названии.

Иногда хочется удалить группу пакетов содержащих что-то общее в названии (к примеру kde или x-server).

Для этого поможет команда dpkg -l 'чего_ищем' - показывает все пакеты удовлетворяющие запросу.

К примеру: удалить все что содержит kde:

  • dpkg -P `dpkg -l '*kde*' | awk '{ print $2 }' | sed '1,6d'`

здесь конвеер в подоболочке:

  • dpkg -P пакет(ы) - удалить пакет(ы) вместе с конфигурационными файлами
  • dpkg -l '*kde*' - показать все пакеты содержащие слово kde в любой части слова
  • awk '{ print $2 }' - печатать только второй столбик (содержащий имена пакетов)
  • sed '1,6d' - удалить первые 6 строк (мусор)

У данного конвеера есть маленький недочет: dpkg пытается удалить даже не установленные пакеты в системе. Скриптик работающий более правильно пусть будет домашним заданием! ;-)

Прочие вкусности.

  • dpkg -r имя_пакета - удалить пакет
  • dpkg -P имя_пакета - удалить пакет вместе с конфигурационными файлами;
  • dpkg -s имя_пакета - показать подробную информацию о пакете;
  • dpkg -L имя_пакета - показать список файлов содержащихся в пакете.
  • dpkg --get-selections - Показывает список установленных пакетов

Убрать варнинги dpkg

У меня при работе с dpkg и apt-get появились такие сообщения

  dpkg: warning: parsing file '/var/lib/dpkg/status' near line 25810 package 'kernel-source-2.4.18':
   error in Version string 'linex3': version number does not start with digit
  dpkg: warning: parsing file '/var/lib/dpkg/available' near line 48390 package 'am-utils':
   'Replaces' field, reference to 'amd': error in version: version number does not start with digit
  dpkg: warning: parsing file '/var/lib/dpkg/available' near line 48393 package 'am-utils':
   'Conflicts' field, reference to 'amd': error in version: version number does not start with digit
   ...

Сообщение в которых фигурирует /var/lib/dpkg/available чистятся командой

  • $ sudo dpkg --clear-avail

Те пакеты, в варнингах которых находится /var/lib/dpkg/status, удалены, но их настройки остались. Для того что бы окончательно почистить на ними можно применить команду apt-get purge

  • $ apt-get purge kernel-source-2.4.18

Заморозить пакет

  • aptitude -t squeeze install php
  • aptitude hold php

system:apt - удалено

Настройка SSH тунеля - [Ключи]

$
0
0

Настройка SSH тунеля

Строим тунель из сети в мир.

ssh

$ ssh-f-N-R2222:10.11.12.13:22 username@99.88.77.66
$ ssh-p345-v-N-R3307:10.11.12.13:3306 username@99.88.77.66

Если ssh запущен на нестандартном порту -p 345

$ ssh-p2222 localhost - мы попадём на хост 10.11.12.13
$ nc localhost -p3307 - попадем на MySql хоста 10.11.12.13

Ключи

  • -f
  • -N
  • -v
  • -p - ssh Порт
  • -R позволяет удаленные обращения (remote) направлять на (local) сервер.
$ ssh-f-N-R2080:10.11.12.14:80 username@99.88.77.66

Введя на хосте 99.88.77.66:

$ w3m -dump http://localhost:2080

Строим тунель из мира в сеть.

SSH

$ ssh-f-N-L4080:192.168.0.10:80 nameuser@88.77.66.55
$ ssh-p345-v-N-L3307:localhost:3306 username@99.88.77.66
$ ssh-L8080:remote-host-which-wait-connect.com:443 username@99.88.77.66

Ключи

  • -f
  • -N не выполнять команды, поднимает только тунель
  • -L позволяет локальные обращения (Local) направлять на удалённый сервер.
  • -v
  • -p - ssh Порт

Аналогично, вводим на своём хосте:

$ w3m -dump http://localhost:4080

и получаем доступ к web-ресурсу узла 192.168.0.10, который находится за хостом 88.77.66.55.

SOCKS5

$ ssh-p22 username@99.88.77.66 -v-N-D3128

Статьи

Паттерны проектирования

$
0
0

Паттерны проектирования

Шаблоны проектирования

Цепочка обязанностей / Chain of Responsibility

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

Команда Команда / Command

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

Итератор / Iterator

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

Посредник / Mediator

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

Снимок / Memento

Позволяет сохранять и восстанавливать прошлые состояния объектов, не раскрывая подробностей их реализации.

Наблюдатель / Observer

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

Состояние / State

Позволяет объектам менять поведение в зависимости от своего состояния. Извне создаётся впечатление, что изменился класс объекта.

Стратегия / Strategy

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

Шаблонный метод / Template Method

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

Посетитель / Visitor

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

Ссылки

Viewing all 1318 articles
Browse latest View live