Nginx несомненно хорош, но заменить апач он сможет только после того, как научится работать с .htaccess.
Использую nginx кеширующим сервером перед апачем, но как отдельный сервер рановато будет, так CMS, которые часто используются в работе, требуют настроек в .htaccess.
Хороший вопрос.
В Nginx никогда не будет поддержки htaccess. Вот обоснование и цифры (к сожалению, на английском).
Если вкратце: такой подход в корне противоречит общему подходу nginx. Если включить htaccess в Apache - это означает, что каждый раз, когда Apache обслуживает файл или каталог, он должен проверить этот каталог и каждый каталог над ним, чтобы узнать, есть ли изменения в htaccess в любом их этих каталогов, при каждом обращении. Это жуткое расточительство и крайне отрицательно сказывается на производительности и потребляемых ресурсах.
Реализовать некую альтернативу, конечно, можно. Но если проводить аналогию - это все равно, что тащить в Linux поддержку виндовых bat-файлов, не желая изучать, например, bash. Хорошее знание (желание разобраться) nginx позволяет переписать любой функционал htaccess используя правильный подход.
На начальном этапе, можно использовать htaccess-конвертер для nginx или то многообразие готовых примеров nginx конфигов для, практически, всех распространенных CMS и фреймворков, которые можно найти в сети.
Лично я не вижу смысла держать апач ради 4-5 строчек в htaccess и успешно избавился от него везде.
Пока мне получалось обойтись одним nginx без апача. Как пример, кубунту.ру и множество других сайтов на одном nginx работает. А про какие CMS идет речь, в которых без .htaccess не обойтись?
Joomla, Opencart.
Но и многие хостеры по-умолчанию используют LAMP, если ты принципиально хочешь что-то иное, нужен VDS.
Для обычных сайтов и интернет-магазинов, необходимости в VDS нет.
Но для высоконагруженных самописных сервисов, это да, лучшего решения чем nginx не найти.
C джумлой не работаю, ничего сказать не могу, а вот opencart вполне себе на nginx без апача работает. Могу пример рабочего конфига nginx под него предоставить. Но у меня да, свой сервер на котором что хочу то и ворочу, сайты на друпале в основном, так же как и кубунту.ру.
Да, пораскинув мозгами можно всй что угодно куда угодно прикрутить, и, скорее всего, это будет действительно работать быстрее.
Но опять же таки, для визитки булочной или парикмахерской, нафиг не нужен VDS, который будет стоить раза в 3-4 дороже, чем обычный ламповый хостинг.
Ну, это не винда, тут не нужны эмуляторы. Вы можете настроить почтовый сервер для локального домена так же, как сделали бы это на реальном сервере. Ключевые слова: sendmail, exim4, dovecot, postfix. Гуглите, выбирайте понравившийся, нужно будет разобраться, что отвечает за отправку, что за хранение, что за предоставление доступа. Плюс потребуется настройка локального DNS.
В /etc/php5/fpm/php.ini, возможно, потребуется настройка таких параметров как sendmail_path (по умолчанию испольуется sendmail, но можно вписать exim4 и т.д. Например: sendmail_path = /usr/sbin/exim4 -t
Также можно указать sendmail_from.
Аналогом PHP mail() является сокетное соединение с удаленным сервером. Примеров реализации в сети навалом, также есть подобные плагины под различные фреймворки/CMS.
Отвечаю на поступивший вопрос: Вот сделали мы типа сервер. А как теперь с другой машины через браузер смотреть его?
На те что вордресс.локал и иже с ними?
На машине где устанавливали вроде все норм. А как с другой?
Ведь прикольнее когда сервер - это другой компьютер.
Мне казалось эти строчки
location / {
try_files $uri $uri/ /index.php;
}
должны что-то делать подобное.
Но заход с другого компа дает тока посмотреть на Вэлком nginx (((
1. Данные строчки работают уже с внутренней структурой виртуального хоста. Подробнее лучше почитать в документации:
про location http://nginx.org/ru/docs/http/ngx_http_core_module.html#location
про try_files http://nginx.org/ru/docs/http/ngx_http_core_module.html#try_files.
2. Если с другой машины отображается welcome to nginx, значит вы не удалили default из sites-enabled. В любом случае, один из хостов вы сможете наблюдать с других машин в сети - тот, который помечен как хост по умолчанию. Обратите внимание на конфиг test.local в статье, я его сделал дефолным через listen 127.0.0.1:80 default;
Важно, что при этом остальные хосты должны быть без ключевого слова default, например в конфиге mysql.local: listen 127.0.0.1:80;
В таком случае, при обращении с другой машины на http://ip_машины_с_nginx/, вы всегда будете попадать в test.local.
3. Для более полного понимания происходящего, желательно изучить основы работы протокола HTTP. Если совсем вкратце и просто, то любой запрос состоит из: типа запроса (GET, POST, PUT...), пути, заголовка и тела запроса.
Когда вы указываете http://test.local/ в браузере, браузер сначала резолвит имя в ip. В случае локального использования - адрес берется из /etc/hosts. После получения ip, браузер отправляет GET запрос следующего вида: GET /
указывая в заголовке host: 'test.local' и еще несколько параметров.
Именно по параметру host из заголовка nginx определяет, какой виртуальный хост запрашивается, после чего обрабатывает url, идущий после GET.
Теперь почему "GET /" - потому, что в случае http://test.local/ идет обращение к корню виртуального хоста. Если бы в браузер был вбит адрес http://test.local/labuda.php, GET выглядел бы так: GET /labuda.php
Или, в случае http://test.local/catalog/labuda.php, был бы таким: GET /catalog/labuda.php
Теперь про обращение с другой машины. Допустим, что ip машины с nginx в сети - 192.168.1.150, тогда в браузере с другой машины этой подсети вы наберете http://192.168.1.150/, при этом запрос будет GET /
а параметр host из заголовка будет содержать 192.168.1.150, но поскольку в конфигах такой не описан, запрос пойдет на хост, помеченный как default (как описано в п.2 выше).
Если вы хотите, чтобы все ваши хосты были доступны с других машин в сети - у вас в этой сети должен быть DNS-сервер, который бы резолвил нужные адреса вроде drupal.local или wordpress.local в ip машины с nginx. Это не часть настройки nginx, это часть настройки сети.
На реальном сервере или VPS/VDS нужно в параметре listen указывать фактический белый (внешний) ip этого сервера/VPS, который будет доступен всем. Опять же, при заходе на http://ip_этого_сервера/ будет выдаваться содержимое виртуального хоста, отмеченного как default. Далее, допустим, вы купили домен kubuntu.ru. Вам нужно делегировать управление его DNS записями двум (для надежности) DNS-серверам. Например, хостинг провайдеры предоставляют такую услугу или можно воспользоваться бесплатным сервисом от яндекса. Как только вы правильно настроите DNS и ваш домен начнет у всех пользователей интернет резолвить ip вашего сервера, при заходе на него через браузер с любой машины последует подключение на ваш сервер с параметром host равным kubuntu.ru. Если ваш сервер настроен на работу с ним - nginx отдаст содержимое, если нет - отдаст default. Аналогично настраиваются поддомены третьего уровня, например ivan.kubuntu.ru, в конфиге будет: ... listen белый_ip_сервера:80; ... server_name ivan.kubuntu.ru; ...
Решил проверить, намедни, как будет работать один из моих форумов на движке vBulletin 4.x на PHP7 (на момент проверки 7.0.3).
Нарвался на забавную несовместимость.
Как известно, в PHP для реализации коллбэков, вместо указателей на функции, используется обращение к функциям через переменные.
<?php
class SomeClass { public function SomeFunc() { echo "SomeFunc called\n"; } };
?>
выдает следующее: PHP Notice: Array to string conversion in /home/max/tmp/test.php on line 33 PHP Notice: Undefined property: SomeClass::$Array in /home/max/tmp/test.php on line 33 PHP Fatal error: Uncaught Error: Function name must be a string in /home/max/tmp/test.php:33 Stack trace: #0 {main} thrown in /home/max/tmp/test.php on line 33
не смотря на то, что is_string($tag_info['callback']) выдает true.
То есть, при вызове воспринимается как массив, а не как элемент ассоциативного массива типа string.
Можно прокостылить так: <?php
Логи - универсальный способ определить причину проблем.
Помимо этого, в случае локальной машины, можно выставить в /etc/php/7.0/fpm/php.ini error_reporting = E_ALL display_errors = On
чтобы все ошибки и предупреждения вываливались прямо на страницу.
Ну, а еще можно заглянуть в документацию https://docs.phpmyadmin.net/en/latest/require.html#php и посмотреть требования =)
Как отключить ошибки "..extension is deprecated.." ?
Перепробовал любые комбинации.
Работает только display_errors = Off но мне нужно другие ошибки видеть...
В корне сайта нет php.ini в index.php тоже отключено.
Вобщем какую директиву не установи все равно ругается на mysql_ нужно mysqli_
php5.5
ps в админ панели выводится содержимое ошибки одной строкой и не сильно напрягает.
А вот на сайте ошибка в типе содержимого. Очевидно перед буфером вываливает и гадит vqmod - но удалить его сейчас нельзя, нужно доделать все. display_errors = Off все отлично.
Яж говорю: любой параметр выводит сообщение о устаревшей функции.
Вот apache тут точно не при чем. Варианта два:
1) вы ошиблись и отредактировали не тот php.ini (от другой версии или от cli);
2) где-то в стриптах есть вызов функции error_reporting(E_ALL); которая переопределяет значение из php.ini.
На коротком скрипте как я показывал выше проверяли?
бесполезная вещь
Как бы не так. Битовые поля и операции с ними позволяют делать самые эффективные структуры данных. Видимо, вы еще не сталкивались с обработкой больших объемов. http://blog.getspool.com/2011/11/29/fast-easy-realtime-metrics-using-redis-bitmaps/ - простой пример, как получить количество уникальных посетителей за текущий день, для 128 миллионов пользователей запрос выполняется за 50 миллисекунд с потреблением памяти всего в 16 мегабайт. При этом результат содержит актуальные данные в реальном времени, без какого-либо кэширования.
Я статью писал в январе 2014-го, надо бы правки внести с учетом новых дистрибутивов...
В 16.04 выбросили старье, имя пакета теперь php7.0-fpm, соответственно названия пакетов с расширениями теперь тоже начинается с 'php7.0-'.
Можно ли не имея домена(только ip) настроить свой сайт для отображения в таком духе ?196.155.1xx.1xx/example.localКак это должно выглядеть в конфиге /etc/nginx/sites-available/example.local
Ну... Не делается так. Точнее, это не будет альтернативой хостам на различных доменах.
Объяснение тут простое.
Если бы речь шла об обработке единичного запроса - проблем никаких, комбинация location/root/rewrite или даже, если хотите, proxy_pass.
Но для приложения (например, набора php-скриптов) у вас не получится, как в случае домена, обойтись настройкой только фронтэнда.
К примеру, картинка или ссылка у вас в итоговом HTML отображается как "/blabla/image.png". Куда пойдет браузер? Конечно на "196.155.1xx.1xx/blabla/image.png", но никак не на "196.155.1xx.1xx/example.local/blabla/image.png".
Даже если у вас будет в скриптах что-то вроде <?php $image_path = 'http://' . $_SERVER['HTTP_HOST'] . '/blabla/image.png'; ?>
то все равно не прокатит.
Какой тут выход? Добавить конфигурационную переменную, например <?php //$host_url_suffix = ''; // оставить пустым, если функционал не требуется $host_url_suffix = '/example.local'; // эти строки где-то в конфиге, $host_url = 'http://' . $_SERVER['HTTP_HOST'] . $host_url_suffix; // в одном экземпляре
$image_path = $host_url . '/blabla/image.png'; // такая обработка на всех страницах ?>
и так касаемо всех картинок и ссылок. То есть, имеет место добавление сего функционала в бэкэнд.
Собственно, в этом случае вы можете разместить скрипты уже в подкаталогах корня одного виртуального хоста и не мучить nginx.
И все же, я советую использовать DNS. Получите бесплатные домены 2-3 уровня и направляйте их на один IP с nginx, неважно, где они находятся.
Зачем заставлять nginx выполнять скрипт.
Я так понимаю index.php должен подключать sitemap.php и уже он анализирует, генерировать ему карту или нет. Если вы хотите напрямую example.com/sitemap.php то наверное так
index index.php sitemap.php
Но лучше тогда по крону+баш и пусть себе генерирует.
Забейте вы на эту карту сайта - утопия и лишняя нагрузка.
Поисковики на нее плевать хотели и ходят как им вздумается.
А поситителей это не добавит.
Вы правы относительно крона.
Разработчики сайта именно так и поступили.
Сейчас по ночам генерируется актуальная копия sitemap.xml
А вот касательно реакции поисковиков(их ботов) на наличие и актуальность файла sitemap.xml, то тут существуют и отличные от вашего мнения.
Однако мой вопрос не совсем про sitemap.xml как таковой(он лишь конкретный повод), а про должное конфигурирование nginx-a.
Надеюсь таки довести его до ума с помощью сообщества.
Осталось только то самое "почти", а именно - мне никак не удаётся заставить nginx выполнить php-скрипт генерации sitemap.xml
Этот php-скрипт (sitemap.php) лежит в корне сайта и, насколько я смог понять его текст, занимается тем, что проверяет наличие файла sitemap.xml и время его модификации. В случае отсутствия или "старости" файла sitemap.xml он вызывает php-скрипт генерации файла sitemap.xml
и по завершении отдаёт его содержимое.
Nginx не выполняет php-скрпиты, он передает запрос бэкэнду (php-fpm), и, когда тот возвращает результат, отдает его клиенту. Это важно понимать, как и каждую директиву в конфиге. Метод "интуитивного тыка" - мало пригоден.
Также предположу, что sitemap.php сразу выплевывает текст XML-ки, как если бы читался .xml файл.
Все мои попытки запросить в браузере этот файл(sitemap.xml) закачиваются в либо 403-им кодом ответа от сервера, либо получением самого текста php-скрипта (sitemap.php), т.е. мне просто отдают php-файл вместо его запуска на сервере.
Если вы видели исходник скрипта, то, скорее всего, пытались сделать как-то так: location / { if (!-e $request_filename){ rewrite ^/sitemap.xml$ /sitemap.php$1 break; } }
Заменяете break на last и будет вам щасье. Хотя...
З.Ы. Конфиг у вас в ужасном состоянии. Зачем дублируете fastcgi*? http://nginx.org/ru/docs/http/ngx_http_fastcgi_module.html#fastcgi_param
Обратите внимание, "Контекст: http, server, location". Т.е. вы можете определить их в контексте сервера (виртуального хоста) или как я показывал выше для отдельного типа файлов и иметь прозрачную структуру, в которой просто ориентироваться и просто изменять, вместо набора дублей.
Ну, тогда стоит последовательно исключать варианты и найти причину.
1. Я написал независимый пример решения, а у вас в location / уже есть рерайт, который... Может поясните, что он делает?
2. sitemap.php действительно, в случае благоприятного исхода, отдает заголовок контент типа text/xml и содержимое. Стоит удостовериться, что при прямом обращении к нему там все выполняется ожидаемо.
3. Условие if (!-e $request_filename) проверяет, что запрашиваемый файл не существует (в данном случае работает аналогично апачевским RewriteCond %{REQUEST_FILENAME} !-f и RewriteCond %{REQUEST_FILENAME} !-d). Соответственно, если у вас существует sitemap.xml - условие выполняться не будет.
4. Сделайте самый минимальный вариант, который точно заработает, а потом уже постепенно добавляйте проверки и т.д., например: location /sitemap.xml { rewrite ^/sitemap.xml$ /sitemap.php$1 last; }
1. Мой вариант рерайта в "location /" - это попытка трансформации htaccess-ой конструкции
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php [L,QSA]
2. Убрал все упоминания про "sitemap" из конфига и запросил в браузере https://cms.mydom.com/sitemap.php
В ответ браузер показал мне текст самого файла sitemap.php
3. Файл с именем sitemap.xml - не существует.
Есть в каталоге /content/export/ файл с другим именем (его по ночам робот генерит и именно его должен был бы отдать, будучи исполненным, sitemap.php)
4. Удалил из конфига ВСЕ location и добавил ваш вариант.
Браузер закачал(не показывая его) мне файл sitemap.txt содержимое которого было тело скрипта sitemap.php.
И это естественно, ведь удалил все упоминания про fastcgi-сотоварищи.
Заменил ваш вариант на свой
location ~ ^/(sitemap.xml) {
fastcgi_index sitemap.php;
fastcgi_param SCRIPT_FILENAME $document_root/sitemap.php;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_pass unix:/var/run/php/php5.6-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_intercept_errors on;
include fastcgi_params;
}
Браузер показал мне тело скрипта sitemap.php
И вот этого я пока объяснить не могу.
Буду признателен за комментарии и новые идеи(подсказки).
1. Рерайт в таком случае вообще не нужен. Поясняю:
RewriteCond %{REQUEST_FILENAME} !-f # если запрос - не существующий файл
RewriteCond %{REQUEST_FILENAME} !-d # и не существующий каталог, то
RewriteRule ^(.*)$ /index.php [L,QSA] # как бы он ни выглядел, изменить его на /index.php, при этом является ссылкой с дописыванием строки запроса.
Подробнее тут - http://httpd.apache.org/docs/current/mod/mod_rewrite.html.
2. Это очень плохо, значит у вас не работает общее направление запросов к php-файлам на бэкэнд (криво описан location ~ \.php$, либо на него пагубно влияют другие части конфига).
3. Ок.
4. Возьмите любой конфиг из моей статьи выше и допишите туда "мой вариант" (location /sitemap.xml).
Еще раз повторюсь: эта конструкция заменяет запрос с /sitemap.xml на /sitemap.php и... флаг last означает, что Nginx ищет другой location, который будет соответствовать этому новому запросу. Найдет правильно описанный location ~ \.php$ - отдаст его php-fpm'у, если нет - отдаст текст скрипта.
Ваш же вариант даже не знаю, как комментировать. Разве что "дорогой nginx! пойди туда, не знаю куда, принеси то, не знаю что". Ну и то, что для конкретного реквеста не нужна регулярка.
Как правильно поставить несколько "одинаковых" условий?
Делаю редирект в зависимости от ip if ($remote_addr != 22.22.22.22) { return 301 https://$server_name$request_uri; } Оно работает.
Нужно несколько IP адресов.
Люди пишут про хак с условиями - мне кажется должен быть другой выход.
----
p.s.
Сам спросил, сам отвечу ) geo $geo { default 0; 22.22.22.22 1; 33.33.33.33 2; }
server { if ($geo = 0) { return 301 https://$server_name$request_uri; } } Все равно выглядит паршиво...
Комментарии (47)
Nginx несомненно хорош, но заменить апач он сможет только после того, как научится работать с .htaccess.
Использую nginx кеширующим сервером перед апачем, но как отдельный сервер рановато будет, так CMS, которые часто используются в работе, требуют настроек в .htaccess.
Хороший вопрос.
В Nginx никогда не будет поддержки htaccess. Вот обоснование и цифры (к сожалению, на английском).
Если вкратце: такой подход в корне противоречит общему подходу nginx. Если включить htaccess в Apache - это означает, что каждый раз, когда Apache обслуживает файл или каталог, он должен проверить этот каталог и каждый каталог над ним, чтобы узнать, есть ли изменения в htaccess в любом их этих каталогов, при каждом обращении. Это жуткое расточительство и крайне отрицательно сказывается на производительности и потребляемых ресурсах.
Реализовать некую альтернативу, конечно, можно. Но если проводить аналогию - это все равно, что тащить в Linux поддержку виндовых bat-файлов, не желая изучать, например, bash. Хорошее знание (желание разобраться) nginx позволяет переписать любой функционал htaccess используя правильный подход.
На начальном этапе, можно использовать htaccess-конвертер для nginx или то многообразие готовых примеров nginx конфигов для, практически, всех распространенных CMS и фреймворков, которые можно найти в сети.
Лично я не вижу смысла держать апач ради 4-5 строчек в htaccess и успешно избавился от него везде.
я правильно понял - если скрипт имеет .htaccess файл, то работать правила не будут по этой инструкции?
Угу, поэтому юзаем вышеуказанный конвертер.
Сходу, вероятно, нет. Но после описания функционала из .htaccess в конфиге nginx - все будет летать.
Пока мне получалось обойтись одним nginx без апача. Как пример, кубунту.ру и множество других сайтов на одном nginx работает. А про какие CMS идет речь, в которых без .htaccess не обойтись?
Joomla, Opencart.
Но и многие хостеры по-умолчанию используют LAMP, если ты принципиально хочешь что-то иное, нужен VDS.
Для обычных сайтов и интернет-магазинов, необходимости в VDS нет.
Но для высоконагруженных самописных сервисов, это да, лучшего решения чем nginx не найти.
C джумлой не работаю, ничего сказать не могу, а вот opencart вполне себе на nginx без апача работает. Могу пример рабочего конфига nginx под него предоставить. Но у меня да, свой сервер на котором что хочу то и ворочу, сайты на друпале в основном, так же как и кубунту.ру.
Навскидку:
http://docs.joomla.org/Nginx
https://github.com/david-rahrer/nginx-opencart
Подобные штуки прекрасно гуглятся. И подсмотреть там ключевые моменты для своего конфига - обычно никаких проблем не составляет.
Да, пораскинув мозгами можно всй что угодно куда угодно прикрутить, и, скорее всего, это будет действительно работать быстрее.
Но опять же таки, для визитки булочной или парикмахерской, нафиг не нужен VDS, который будет стоить раза в 3-4 дороже, чем обычный ламповый хостинг.
Joomla спокойно живет и в nginx.
Как можно поставить почтовый эмулятор? Чтобы проверять как работает mail() или Mail.
Ну, это не винда, тут не нужны эмуляторы. Вы можете настроить почтовый сервер для локального домена так же, как сделали бы это на реальном сервере. Ключевые слова: sendmail, exim4, dovecot, postfix. Гуглите, выбирайте понравившийся, нужно будет разобраться, что отвечает за отправку, что за хранение, что за предоставление доступа. Плюс потребуется настройка локального DNS.
В /etc/php5/fpm/php.ini, возможно, потребуется настройка таких параметров как sendmail_path (по умолчанию испольуется sendmail, но можно вписать exim4 и т.д. Например:
sendmail_path = /usr/sbin/exim4 -t
Также можно указать sendmail_from.
Аналогом PHP mail() является сокетное соединение с удаленным сервером. Примеров реализации в сети навалом, также есть подобные плагины под различные фреймворки/CMS.
Отвечаю на поступивший вопрос:
1. Данные строчки работают уже с внутренней структурой виртуального хоста. Подробнее лучше почитать в документации:
про location
http://nginx.org/ru/docs/http/ngx_http_core_module.html#location
про try_files
http://nginx.org/ru/docs/http/ngx_http_core_module.html#try_files.
2. Если с другой машины отображается welcome to nginx, значит вы не удалили default из sites-enabled. В любом случае, один из хостов вы сможете наблюдать с других машин в сети - тот, который помечен как хост по умолчанию. Обратите внимание на конфиг test.local в статье, я его сделал дефолным через
listen 127.0.0.1:80 default;
Важно, что при этом остальные хосты должны быть без ключевого слова default, например в конфиге mysql.local:
listen 127.0.0.1:80;
В таком случае, при обращении с другой машины на http://ip_машины_с_nginx/, вы всегда будете попадать в test.local.
3. Для более полного понимания происходящего, желательно изучить основы работы протокола HTTP. Если совсем вкратце и просто, то любой запрос состоит из: типа запроса (GET, POST, PUT...), пути, заголовка и тела запроса.
Когда вы указываете http://test.local/ в браузере, браузер сначала резолвит имя в ip. В случае локального использования - адрес берется из /etc/hosts. После получения ip, браузер отправляет GET запрос следующего вида:
GET /
указывая в заголовке host: 'test.local' и еще несколько параметров.
Именно по параметру host из заголовка nginx определяет, какой виртуальный хост запрашивается, после чего обрабатывает url, идущий после GET.
Теперь почему "GET /" - потому, что в случае http://test.local/ идет обращение к корню виртуального хоста. Если бы в браузер был вбит адрес http://test.local/labuda.php, GET выглядел бы так:
GET /labuda.php
Или, в случае http://test.local/catalog/labuda.php, был бы таким:
GET /catalog/labuda.php
Теперь про обращение с другой машины. Допустим, что ip машины с nginx в сети - 192.168.1.150, тогда в браузере с другой машины этой подсети вы наберете http://192.168.1.150/, при этом запрос будет
GET /
а параметр host из заголовка будет содержать 192.168.1.150, но поскольку в конфигах такой не описан, запрос пойдет на хост, помеченный как default (как описано в п.2 выше).
Если вы хотите, чтобы все ваши хосты были доступны с других машин в сети - у вас в этой сети должен быть DNS-сервер, который бы резолвил нужные адреса вроде drupal.local или wordpress.local в ip машины с nginx. Это не часть настройки nginx, это часть настройки сети.
На реальном сервере или VPS/VDS нужно в параметре listen указывать фактический белый (внешний) ip этого сервера/VPS, который будет доступен всем. Опять же, при заходе на http://ip_этого_сервера/ будет выдаваться содержимое виртуального хоста, отмеченного как default. Далее, допустим, вы купили домен kubuntu.ru. Вам нужно делегировать управление его DNS записями двум (для надежности) DNS-серверам. Например, хостинг провайдеры предоставляют такую услугу или можно воспользоваться бесплатным сервисом от яндекса. Как только вы правильно настроите DNS и ваш домен начнет у всех пользователей интернет резолвить ip вашего сервера, при заходе на него через браузер с любой машины последует подключение на ваш сервер с параметром host равным kubuntu.ru. Если ваш сервер настроен на работу с ним - nginx отдаст содержимое, если нет - отдаст default. Аналогично настраиваются поддомены третьего уровня, например ivan.kubuntu.ru, в конфиге будет:
...
listen белый_ip_сервера:80;
...
server_name ivan.kubuntu.ru;
...
Решил проверить, намедни, как будет работать один из моих форумов на движке vBulletin 4.x на PHP7 (на момент проверки 7.0.3).
Нарвался на забавную несовместимость.
Как известно, в PHP для реализации коллбэков, вместо указателей на функции, используется обращение к функциям через переменные.
<?php
class SomeClass
{
public function SomeFunc()
{
echo "SomeFunc called\n";
}
};
$obj = new SomeClass;
?>
Такой вариант продолжает работать:
<?php
$callback = 'SomeFunc';
$obj->$callback();
?>
А такой:
<?php
$tag_info['callback'] = 'SomeFunc';
$obj->$tag_info['callback']();
?>
выдает следующее:
PHP Notice: Array to string conversion in /home/max/tmp/test.php on line 33
PHP Notice: Undefined property: SomeClass::$Array in /home/max/tmp/test.php on line 33
PHP Fatal error: Uncaught Error: Function name must be a string in /home/max/tmp/test.php:33
Stack trace:
#0 {main}
thrown in /home/max/tmp/test.php on line 33
не смотря на то, что is_string($tag_info['callback']) выдает true.
То есть, при вызове воспринимается как массив, а не как элемент ассоциативного массива типа string.
Можно прокостылить так:
<?php
$tag_info['callback'] = 'SomeFunc';
$callback = $tag_info['callback'];
$obj->$callback();
?>
либо использовать области видимости при подобных вызовах (новая фича 7 версии).
Логи - универсальный способ определить причину проблем.
Помимо этого, в случае локальной машины, можно выставить в /etc/php/7.0/fpm/php.ini
error_reporting = E_ALL
display_errors = On
чтобы все ошибки и предупреждения вываливались прямо на страницу.
Ну, а еще можно заглянуть в документацию https://docs.phpmyadmin.net/en/latest/require.html#php и посмотреть требования =)
Как отключить ошибки "..extension is deprecated.." ?
Перепробовал любые комбинации.
Работает только display_errors = Off но мне нужно другие ошибки видеть...
В корне сайта нет php.ini в index.php тоже отключено.
Вобщем какую директиву не установи все равно ругается на mysql_ нужно mysqli_
php5.5
ps в админ панели выводится содержимое ошибки одной строкой и не сильно напрягает.
А вот на сайте ошибка в типе содержимого. Очевидно перед буфером вываливает и гадит vqmod - но удалить его сейчас нельзя, нужно доделать все. display_errors = Off все отлично.
Вот apache тут точно не при чем. Варианта два:
1) вы ошиблись и отредактировали не тот php.ini (от другой версии или от cli);
2) где-то в стриптах есть вызов функции error_reporting(E_ALL); которая переопределяет значение из php.ini.
На коротком скрипте как я показывал выше проверяли?
Как бы не так. Битовые поля и операции с ними позволяют делать самые эффективные структуры данных. Видимо, вы еще не сталкивались с обработкой больших объемов.
http://blog.getspool.com/2011/11/29/fast-easy-realtime-metrics-using-redis-bitmaps/ - простой пример, как получить количество уникальных посетителей за текущий день, для 128 миллионов пользователей запрос выполняется за 50 миллисекунд с потреблением памяти всего в 16 мегабайт. При этом результат содержит актуальные данные в реальном времени, без какого-либо кэширования.
в vqmod/vqcache/vq2-system_startup.php:error_reporting(E_ALL);что за идиот его придумал(vqmod)...
Не могу поставить php5-fpm на 16.04 - package is not available
Вероятно потому, что в 16.04 php 7-ой версии.
sudo apt install php7-fpm
Я статью писал в январе 2014-го, надо бы правки внести с учетом новых дистрибутивов...
В 16.04 выбросили старье, имя пакета теперь php7.0-fpm, соответственно названия пакетов с расширениями теперь тоже начинается с 'php7.0-'.
Возможно на всю эту связку поставить php 5.5 (как 14,04)?
Чтобы для конкретного хоста можно устанавливать версию php.
Получилась жопа конкретная. Работает только PhpMyadmin и самописные скрипты, все остальное нужно фактически допиливать с нуля - это не реально.
Честно говоря я не понял для чего php_backends и где этот файл должен быть?
Работает.
а как насчет расширений
мне нужен DOMDocument php-xml он уже установлен.
Как выглядит инсталяция для других версий?
p.s.
Если я при установке php5 согласился(погарячился) скопировать конфиг от php7 - как его сгенерировать по новой?
Можно ли не имея домена(только ip) настроить свой сайт для отображения в таком духе ?
196.155.1xx.1xx/example.local
Как это должно выглядеть в конфиге /etc/nginx/sites-available/example.localНу... Не делается так. Точнее, это не будет альтернативой хостам на различных доменах.
Объяснение тут простое.
Если бы речь шла об обработке единичного запроса - проблем никаких, комбинация location/root/rewrite или даже, если хотите, proxy_pass.
Но для приложения (например, набора php-скриптов) у вас не получится, как в случае домена, обойтись настройкой только фронтэнда.
К примеру, картинка или ссылка у вас в итоговом HTML отображается как "/blabla/image.png". Куда пойдет браузер? Конечно на "196.155.1xx.1xx/blabla/image.png", но никак не на "196.155.1xx.1xx/example.local/blabla/image.png".
Даже если у вас будет в скриптах что-то вроде
<?php
$image_path = 'http://' . $_SERVER['HTTP_HOST'] . '/blabla/image.png';
?>
то все равно не прокатит.
Какой тут выход? Добавить конфигурационную переменную, например
<?php
//$host_url_suffix = ''; // оставить пустым, если функционал не требуется
$host_url_suffix = '/example.local'; // эти строки где-то в конфиге,
$host_url = 'http://' . $_SERVER['HTTP_HOST'] . $host_url_suffix; // в одном экземпляре
$image_path = $host_url . '/blabla/image.png'; // такая обработка на всех страницах
?>
и так касаемо всех картинок и ссылок. То есть, имеет место добавление сего функционала в бэкэнд.
Собственно, в этом случае вы можете разместить скрипты уже в подкаталогах корня одного виртуального хоста и не мучить nginx.
И все же, я советую использовать DNS. Получите бесплатные домены 2-3 уровня и направляйте их на один IP с nginx, неважно, где они находятся.
Зачем заставлять nginx выполнять скрипт.
Я так понимаю index.php должен подключать sitemap.php и уже он анализирует, генерировать ему карту или нет. Если вы хотите напрямую example.com/sitemap.php то наверное так
index index.php sitemap.php
Но лучше тогда по крону+баш и пусть себе генерирует.
Забейте вы на эту карту сайта - утопия и лишняя нагрузка.
Поисковики на нее плевать хотели и ходят как им вздумается.
А поситителей это не добавит.
ps ждем более компетентного ответа)
Вы правы относительно крона.
Разработчики сайта именно так и поступили.
Сейчас по ночам генерируется актуальная копия sitemap.xml
А вот касательно реакции поисковиков(их ботов) на наличие и актуальность файла sitemap.xml, то тут существуют и отличные от вашего мнения.
Однако мой вопрос не совсем про sitemap.xml как таковой(он лишь конкретный повод), а про должное конфигурирование nginx-a.
Надеюсь таки довести его до ума с помощью сообщества.
Nginx не выполняет php-скрпиты, он передает запрос бэкэнду (php-fpm), и, когда тот возвращает результат, отдает его клиенту. Это важно понимать, как и каждую директиву в конфиге. Метод "интуитивного тыка" - мало пригоден.
Также предположу, что sitemap.php сразу выплевывает текст XML-ки, как если бы читался .xml файл.
Если вы видели исходник скрипта, то, скорее всего, пытались сделать как-то так:
location / {
if (!-e $request_filename){
rewrite ^/sitemap.xml$ /sitemap.php$1 break;
}
}
Хотя, если почитать http://nginx.org/ru/docs/http/ngx_http_rewrite_module.html#rewrite, там есть описание флагов:
Заменяете break на last и будет вам щасье. Хотя...
З.Ы. Конфиг у вас в ужасном состоянии. Зачем дублируете fastcgi*?
http://nginx.org/ru/docs/http/ngx_http_fastcgi_module.html#fastcgi_param
Обратите внимание, "Контекст: http, server, location". Т.е. вы можете определить их в контексте сервера (виртуального хоста) или как я показывал выше для отдельного типа файлов и иметь прозрачную структуру, в которой просто ориентироваться и просто изменять, вместо набора дублей.
Ну, тогда стоит последовательно исключать варианты и найти причину.
1. Я написал независимый пример решения, а у вас в location / уже есть рерайт, который... Может поясните, что он делает?
2. sitemap.php действительно, в случае благоприятного исхода, отдает заголовок контент типа text/xml и содержимое. Стоит удостовериться, что при прямом обращении к нему там все выполняется ожидаемо.
3. Условие if (!-e $request_filename) проверяет, что запрашиваемый файл не существует (в данном случае работает аналогично апачевским RewriteCond %{REQUEST_FILENAME} !-f и RewriteCond %{REQUEST_FILENAME} !-d). Соответственно, если у вас существует sitemap.xml - условие выполняться не будет.
4. Сделайте самый минимальный вариант, который точно заработает, а потом уже постепенно добавляйте проверки и т.д., например:
location /sitemap.xml {
rewrite ^/sitemap.xml$ /sitemap.php$1 last;
}
1. Мой вариант рерайта в "location /" - это попытка трансформации htaccess-ой конструкции
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php [L,QSA]
2. Убрал все упоминания про "sitemap" из конфига и запросил в браузере https://cms.mydom.com/sitemap.php
В ответ браузер показал мне текст самого файла sitemap.php
3. Файл с именем sitemap.xml - не существует.
Есть в каталоге /content/export/ файл с другим именем (его по ночам робот генерит и именно его должен был бы отдать, будучи исполненным, sitemap.php)
4. Удалил из конфига ВСЕ location и добавил ваш вариант.
Браузер закачал(не показывая его) мне файл sitemap.txt содержимое которого было тело скрипта sitemap.php.
И это естественно, ведь удалил все упоминания про fastcgi-сотоварищи.
Заменил ваш вариант на свой
location ~ ^/(sitemap.xml) {
fastcgi_index sitemap.php;
fastcgi_param SCRIPT_FILENAME $document_root/sitemap.php;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_pass unix:/var/run/php/php5.6-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_intercept_errors on;
include fastcgi_params;
}
Браузер показал мне тело скрипта sitemap.php
И вот этого я пока объяснить не могу.
Буду признателен за комментарии и новые идеи(подсказки).
1. Рерайт в таком случае вообще не нужен. Поясняю:
RewriteCond %{REQUEST_FILENAME} !-f # если запрос - не существующий файл
RewriteCond %{REQUEST_FILENAME} !-d # и не существующий каталог, то
RewriteRule ^(.*)$ /index.php [L,QSA] # как бы он ни выглядел, изменить его на /index.php, при этом является ссылкой с дописыванием строки запроса.
Подробнее тут - http://httpd.apache.org/docs/current/mod/mod_rewrite.html.
try_files $uri $uri/ /index.php?$args; # пробуем оригинальный запрашиваемый URI, потом его же как каталог (черта дроби в конце), и если все, кроме последнего отсутствуют - делаем внутреннее перенаправление на последний.
Подробнее тут - http://nginx.org/ru/docs/http/ngx_http_core_module.html#try_files.
Про зло - https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/.
2. Это очень плохо, значит у вас не работает общее направление запросов к php-файлам на бэкэнд (криво описан location ~ \.php$, либо на него пагубно влияют другие части конфига).
3. Ок.
4. Возьмите любой конфиг из моей статьи выше и допишите туда "мой вариант" (location /sitemap.xml).
Еще раз повторюсь: эта конструкция заменяет запрос с /sitemap.xml на /sitemap.php и... флаг last означает, что Nginx ищет другой location, который будет соответствовать этому новому запросу. Найдет правильно описанный location ~ \.php$ - отдаст его php-fpm'у, если нет - отдаст текст скрипта.
Ваш же вариант даже не знаю, как комментировать. Разве что "дорогой nginx! пойди туда, не знаю куда, принеси то, не знаю что". Ну и то, что для конкретного реквеста не нужна регулярка.
Как правильно поставить несколько "одинаковых" условий?
Делаю редирект в зависимости от ip
if ($remote_addr != 22.22.22.22) {
Оно работает.return 301 https://$server_name$request_uri;
}
Нужно несколько IP адресов.
Люди пишут про хак с условиями - мне кажется должен быть другой выход.
----
p.s.
Сам спросил, сам отвечу )
geo $geo {
Все равно выглядит паршиво...default 0;
22.22.22.22 1;
33.33.33.33 2;
}
server {
if ($geo = 0) {
return 301 https://$server_name$request_uri;
}
}
Отправить комментарий