Как переопределяется логирование в NGINX

Опубликовано:
Автор:

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

Без директив error_log, access_log

В конфигурационном файле nginx.conf, а также во всех подключаемых файлах отсутствуют директивы error_log, access_log.

Результат. Сообщения пишутся в файлы: /var/log/nginx/access.log (лог доступа) и /var/log/nginx/error.log (лог ошибок).

Директивы access_log в секции http

В секции http объявляем директиву access_log

http {
  ...
  access_log  /var/log/nginx-access.log main;
  ... 
}

Результат. После перезагрузки NGINX сообщения пишутся в файл /var/log/nginx-access.log

Добавляем второй access_log сразу за первым

http {
  ...
  access_log  /var/log/nginx-access.log main;
  access_log  /var/log/nginx-access-2.log compress;
  ...
}

Результат. После перезагрузки NGINX сообщения пишутся в оба лога. Мы получаем одни и те же записи в логах, но записи имеют разную структур: зависит от того, как настроены log_format main и log_format compress.

Отмена access_log

Сразу за строками access_log добавляем access_log off

http {
  ...
  access_log  /var/log/nginx-access.log main;
  access_log  /var/log/nginx-access-2.log compress;
  access_log  off;
  ...
}

Результат. После перезагрузки NGINX сообщения в логи не пишутся.

Добавим следом еще одну директиву access_log

http {
  ...
  access_log  /var/log/nginx-access.log main;
  access_log  /var/log/nginx-access-2.log compress;
  access_log  off;
  access_log  /var/log/nginx-access.log main;
  ...
}

Результат. После перезагрузки NGINX сообщения в логи не пишутся. Директива access_log off действует на всем уровне секции http независимо, где она определена в конце или в самом начале.

Удалим все директивы access_log из секции http, кроме access_log off и добавим access_log в секцию server.

http {
  ...
  access_log  off;
  server {
    server_name     host.name.one;
    access_log      /var/log/nginx-access.log main;
  }
  server {
    server_name     host.name.two;
  }
}

Результат. После перезагрузки NGINX для сервера host.name.one сообщения пишутся в лог, а для сервера host.name.two – нет. Если директива access_log off однажды определена, то переопределить ее можно только во вложенной секции.

Переместим директиву access_log в самый низ секции server

http {
  ...
  access_log  off;
  server {
    server_name     host.name.one;
    # Блокировка нежелательных ботов
    if ($black_agent = "1") { return 404; }
    # Редирект на адреса без слеша в конце
    rewrite ^/(.*)/$ /$1 permanent;
    access_log      /var/log/nginx-access.log main;
  }
}

Результат. Сообщения блокировки (404) и редиректа (301) в лог пишутся, на них не действует родительский access_log off, потому что в дочерней секции server определена директива access_log – пусть и в самом конце, это неважно.

Дополнение. Команды для тестов логирования

Удалить журналы и перезапустить NGINX

sudo rm /var/log/nginx/*; sudo systemctl restart nginx;

Проверить конфигурацию на корректность и перезапустить NGINX

sudo nginx -t && sudo systemctl restart nginx

Запрос для ответа с кодом 200 (динамический файл)

wget --spider -S "http://site/sitemap.xml" 2>&1 | grep "HTTP/" | awk '{print $2}'

Запрос для ответа с кодом 200 (статический файл)

wget --spider -S "http://site.ru/robots.txt/" 2>&1 | grep "HTTP/" | awk '{print $2}'

Запрос для ответа с кодами 301, 200 (настроена переадресация)

wget --spider -S "http://sub.site.ru/robots.txt" 2>&1 | grep "HTTP/" | awk '{print $2}'

Блокировка без ответа, код 444 (настроена блокировка)

wget --method=PUT "http://site.ru/file.txt"

Блокировка бота c ответом, код 404 (настроена блокировка)

wget -U SemrushBot --spider -S "http://site.ru/" 2>&1 | grep "HTTP/" | awk '{print $2}'