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

Gena Makhomed gmm на csdoc.com
Сб Ноя 13 22:19:26 MSK 2010


On 13.11.2010 19:53, Maxim Dounin wrote:

>>> It would be good to have something like '-e' switch instead,
>>> similar to '-p' for prefix (actually, I even have it in my TODO
>>> since 0.7.53, but ENOTIME).
>>
>> примерно так сейчас Apache и делает:
>>
>> # httpd -h 2>&1 | grep error
>>    -e level           : show startup errors of level (see LogLevel)
>>    -E file            : log startup errors to file
>>
>> но это не очень красивое решение, потому что инофрмация тут дублируется,
>> да и с pid-файлом будут аналогичные проблемы, тогда еще один ключ надо?

> С pid-файлом таких проблем быть не может - он создаётся уже после
> заверешения парсинга конфига.

в исходном сообщении от Hongli Lai из англоязычной рассылки было:

"have a setup in which many different users use the same Nginx
executable, but each one with a different config file
and error log file"

а чтобы управлять различными экземплярами nginx, которые запущены
из одного бинарника и отличаются только конфигом и init-скриптом,
их надо уметь различать. а различать их можно только через PID.

вариант парсить в инит-скрипте вывод "ps -ef", чтобы определить
pid необходимого nginx master процесса - это достаточно недоубно.
вариант pidfile=`nginx -c $config -G pid` мне видится тут лучшим.

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

или придется добавлять к nginx еще один параметр командной строки -P

   -P pidfile    : set pid file name (default: /var/run/nginx.pid)

или два раза дублировать имя pid-файла - в init-скрипте и в конфиге.
но если информация где-то дублируется несколько раз, то рано или поздно
будут возникать проблемы у пользователей, когда они изменили директиву
pid в конфиге, но забыли изменить параметр командной строки nginx
в init-скрипте, или наоборот.

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

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

тем более, что если в конфиге нет директивы error_log,
то все работает как и раньше, используя biult-in defaults.

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

>> 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.

> Сейчас nginx не умеет "провернуть фарш назад", т.е. достать
> исходную строку как она была в конфиге.  А даже если бы и умел:
> для pid'а в общем случае нужна не исходная строка, а то во что она
> превратилась после применения префикса.

> Так что сделать подобную функциональность универсальной - будет
> нетривиально, фактически нужно каждую директиву учить себя
> доставать обратно.

все не надо. пока что надо только две: pid и error_log.
просто я предлагаю более универсальный вариант параметра -G
чтобы не пришлось потом на каждую отдельную директиву делать
свой собственный ключ командной строки:

-P для задания имени pid-файла
-E для задания имени startup errors файла
-e для задания startup errors LogLevel

и т.п.

> С другой стороны - вот именно для pid'а может быть и имеет смысл
> сделать.

для error_log это тоже имеет смысл сделать,
чтобы потом при парсинге конфига писать сообщения об ошибках
именно в тот error_log, который соответствует этому экземпляру nginx,
а не в дефолтовый error.log, откуда потом будет очень трудно/невозможно
понять в каком из экземпляров nginx произошла ошибка.

P.S.

если нельзя реализовать эту feature средствами nginx, тогда можно будет
сделать скрипт nginx_conf_helper, который будет по заданному -c $config
вытаскивать из конфига значения директив pid и error_log, которые потом
можно будет использовать в init-скрипте nginx, без дублирования
информации в конфиге nginx и в файле /etc/sysconfig/nginx:

/etc/nginx/nginx-static.conf
===================================
error_log /var/log/nginx/nginx-static.error.log debug;
pid /var/run/nginx-static.pid;


/etc/sysconfig/nginx-static
===================================
config=/etc/nginx/nginx-static.conf
error_log_file=/var/log/nginx/nginx-static.error.log
error_log_level=debug
pid=/var/run/nginx-static.pid

/etc/init.d/nginx-static
======================================
start:
     daemon nginx -c $config -E $error_log_file -e $error_log_level

reload:
     killproc -p $pid -HUP

и т.д. и т.п.

-- 
Best regards,
  Gena




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