Re: глобальные директивы error_log и pid

Gena Makhomed gmm на csdoc.com
Вс Ноя 14 21:17:18 MSK 2010


On 14.11.2010 2:40, Maxim Dounin wrote:

> Pid можно задать в конфиге или через -g "pid $pidfile;".  Никаких
> дополнительных ключей для того чтобы его задавать - вводить не
> нужно.

если pid задать в конфиге nginx, то дополнительно нужно будет указывать
то же самое значение и в /etc/sysconfig/nginx, чтобы init-script мог
управлять этим экземпляром nginx. и при изменении nginx.conf надо будет
не забыть поправить также и второй конфиг /etc/sysconfig/nginx
дублирование информации неудобно и будет провоцировать ошибки.

если pid задавать только в одном файле /etc/sysconfig/nginx
и передавать его в nginx через -g "pid $pidfile;" -
тогда появится две достаточно неприятные проблемы:

- перестанет нормально работать nginx -s stop|quit|reopen|reload,
потому что вместо $pidfile будет использоваться built-in default
и для управления nginx теперь необходимо будет использовать
только init-скрипт.

создатели httpd, кстати уже наступили на эти грабли и создали shell-
cкрипт apachectl, который считывает конфиг /etc/sysconfig/httpd
и только после этого запускакает httpd c заданными параметрами.
тут придется тоже при таком подходе создавать скрипт nginxctl

- вместо единственного конфигурационного файла /etc/nginx/nginx.conf
которым полностью задавалось поведение nginx их теперь будет два, при
внесении изменений в конфиг, просматривать и править надо будет уже оба.

по этим причинам я ключ -g стараюсь вообще не использовать.
а в /etc/sysconfig/nginx задаю только путь к конфигу nginx.

аналогичные проблемы будут и если сделать -g " error_log ...; "
или такие же как у апача ключи коммандной строки nginx -e и -E.

>>>> я придумал более красивое решение:
>>>>
>>>> 1. nginx определяет имя конфигурационного файла из параметра -с
>>>>     или используется built-in значение, если ключ -c не определен.
>>>>
>>>> 2. вызывается helper-функция, которая парсит конфигурационный файл,
>>>>     считывая только несколько глобальных директив: error_log и pid,
>>>>     если эти две директивы встретились в конфиге, парсинг прекращается.
>>>>     директива include также игнорируется, как и возможные ошибки разбора.
>>>
>>> Вопрос на самом деле очень простой: если мы хотим куда-то
>>> логировать ошибки открытия/парсинга конфига - то должны откуда-то ещё
>>> получить место для логирования этих ошибок.
>>>
>>> Сейчас это "откуда-то ещё" - --error-log-path из бинарника (и
>>> префикс из бинарника или из ключа -p, если путь в --error-log-path
>>> относительный).

делать много каталогов - это не выход, в Linux принят подход
Filesystem Hierarchy Standard (http://www.pathname.com/fhs/)
так что все error-логи nginx находятся в одном каталоге
/var/log/nginx/ - так что ключ -p тут ничем не поможет.

>>> Предлагаемое решение в качестве "откуда-то ещё" сделать
>>> дополнительный sloppy-parser конфига мне кажется крайне
>>> сомнительным.
>>
>> по такому же приципу работают и современные операционные системы -
>> для того чтобы загрузить ядро необходимо получить доступ к файловой
>> системе, а чтобы получить доступ к файловой системе - надо чтобы ядро
>> уже было запущено. и загрузчик операционной системы выполняет роль
>> такого "упрощенного парсера", который умеет только читать файлы.
>
> Угу, и я даже и говорить не хочу сколько в этом месте имеется в
> результате геморроя.
>
>> тем более, что если в конфиге нет директивы error_log,
>> то все работает как и раньше, используя biult-in defaults.
>>
>> а если в конфиге nginx указана директива error_log,
>> тогда все работает ожидаемым для пользователя образом,
>> это принцип "наименьшего сюрприза". иначе - как и сейчас,
>> будет очень много вопросов в списках рассылки, почему они
>> указали директиву error_log в конфиге, а nginx пишет не туда.
>
> Я не говорил, что мне не нравится идея брать error_log из конфига.
> Я говорил, что мне не нравится идея делать sloppy-parser этого
> конфига.  Это будет приличный кусок дополнительного кода, нужного
> только для одной задачи - вытащить error_log.

т.е. все-таки лучше/проще делать это внешним скриптом на python ?

> И ладно бы это решало проблему, так ведь полностью оно её не
> решает: если конфиг не открылся или там syntax error до
> error_log'а - всё равно придётся сваливаться в --error-log-path.

на этапе определения только error_log`а
все ошибки до error_log`а можно и даже нужно игнорировать.

всё что нам надо - это найти не в комментариях, не внутри блока
и не внутри кавычек фрагмент текста error_log и вытащить всё,
что стоит после этой последовательности символов 'error_log'
до закрывающего символа ';' и при необходимости добавить prefix.

после этого - устанавливаем внутри nginx значение переменной
ngx_str_t error_log вместо ngx_string(NGX_ERROR_LOG_PATH);
и начинаем полноценный парсинг конфига, как и раньше.

если конфиг не открылся - тогда да, выходит что без вариантов,
надо будет сваливаться в дефолтовый /var/log/nginx/error.log
но такие ситуации будут достаточно редкими.

> А мне, например, нужно *вообще никогда* не трогать
> --error-log-path, потому как тот же test suite предполагает
> возможность запуска на произвольно скомпилированном бинарнике без
> каких-либо последствий для системы.

не совсем понимаю, как сейчас его получается не трогать,
ведь директива error_log из конфига переопределяет дефолтовое
значение переменной error_log, которое было задано в --error-log-path.

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

>>>> 5. добавляется всего один параметр командной строки -G
>>>>
>>>>    -G directive  : get global directive from configuration file
>>>>
>>>> это необходимо для того, чтобы можно было seamless использовать
>>>> один бинарник nginx для запуска нескольких независимых instances:
>>>>
>>>> pidfile=`nginx -G pid`
>>>>
>>>> и дальше init-script знает, какой pid file отвечает этому экземпляру.
>>>> причем, вся конфигурация nginx находится только в одном месте - конфиге.
>>
>>> Just a side note: это не имеет ну никакого отношения к проблеме
>>> error_log'а.
>>
>> верно.
>>
>> это другая проблема, которая появится у Hongli Lai
>> после того как он решит эту проблему с erorr_log`ом.
>>
>> я просто уже прошелся по всем этим граблям несколько раз,
>> когда пытался сделать несколько nginx instances на одном binary.
>
> Ходить по граблям не запретишь, но в отличие от error_log'а -
> проблемы с заданием pid просто нет.
>
> Есть небольшое неудобство, заключающееся в необходмости задавать
> его и в конфиге и в init-скрипте (либо только в init-скрипте, но
> соответственно отдельно от остального конфига).
>
> Я лишь указал на проблемы предлагаемого подхода разрешния данного
> неудобства.

ясно. спасибо. лично меня устроит практически любое решение -
определение пути к лог-файлу и loglevel через ключи nginx -E и -e,
тоже подходит, тогда можно будет внешним скриптом парсить конфиг
nginx и в init-script`е устанавливать значение этих параметров
командной строки перед запуском nginx из init-скрипта,
и nginx -s stop|quit|reopen|reload тоже будет работать
потому что вся конфигурация будет только в nginx.conf.

P.S. у меня такое ощущение, что при использовании apache-подхода
проблем будет намного больше из-за "размазывания" конфигурации
по нескольким файлам и как следствие этого, например,
необходимости использования shell-скрипта nginxctl
вместо теперешнего nginx -s stop|quit|reopen|reload
и т.п. проблемы.

-- 
Best regards,
  Gena




Подробная информация о списке рассылки nginx-ru