How to Install Logrotate and Configure Nginx Log Rotation
Logrotate is a utility designed to ease administration of systems that generate large numbers of log files. It takes care of automatic log file rotation, compression, removal, and mailing of log files. All the services or applications deployed on the server generates log’s in a file for each action that is performed on the system/application/ by a user. Over a period of time, it becomes a tedious task to manage such log files. These log files will grow in large sizes and the application performance would deteriorate periodically. On a long term, it will contribute to a potential risk of making a system unresponsive due to the lack of disk space.
To mitigate such issues and maintain log files we utilize “logrotate”. This tool is designed to simplify the management of log files on systems that generate many large log files.
In this article, we will talk more about logrotate utility and how to configure Nginx log rotation.
Installation
In most distributions, it is installed and configured by default. In order to install the package, check if the package is installed, else install the package as described.
Here, it seems to be installed by default. If this query reports none, then you can install it on a CentOS 7 server with the command below:
Running logrotate
Logrotate helps system administrators to systematically rotate and archive any log files produced by the system and thereby reducing an operating system’s disk space requirement. Normally, logrotate run as a daily cron job. It will not modify a log multiple times in a day.
Understanding the Configuration files
By default, when the logrotate is installed, you can locate its main configuration file here: /etc/logrotate.conf
Logrotate includes the directory /etc/logrotate.d/ where you configure the different logs (daemons and services on which you want to rotate logs). All the service specific configuration files are stored in /etc/logrotate.d/ .
The main configuration file /etc/logrotate.conf contains a generic configuration. Please take a look at my default logrotate configuration file:
Line 3 — weekly: This configuration option ensures a weekly rotation of all log files defined in main configuration file and in /etc/logrotate.d/ directory.
Line 6 — rotate 4: It ensures that logrotate keeps a 4 weeks backup of all log files.
Line 9 — create: this option instructs logrotate to create new empty log files after each rotation
Line 12 — dateext: This appends an extension to all rotated log files in form of date when each particular log file was processed by logrotate
Line 15 — compress: This compresses the rotated log file.
Line 18 — include /etc/logrotate.d: This include all other configuration from directory /etc/logrotate.d.
Line 21 — 33 contains a specific service log rotate configuration
Configuring Nginx logrotation
For most of the services a default service log rotate configuration file will be created automatically in the /etc/logrotate.d/ folder. All packages usually include a log rotation configuration, even if logrotate is not installed on the system. However, if we have compiled Nginx from sources, it will be necessary to define our own log rotation settings manually inside the /etc/logrotate.d/ folder with the log file location mentioned in the Nginx configuration file.
Please see the default Nginx log rotation configuration created on my server by the installation.
Line 1 — /var/log/nginx/*log: This defines all the Nginx log files located at /var/log/nginx/. TIP: If you wish to include multiple log files in a single configuration file use wildcard, just like this «/var/log/nginx/*log». For a single log file, you can just mention that log file as «/var/log/nginx/error.log».
Line 2 — create: This creates a new log file and set the permission 644 with the ownership nginx.
Line 3 — daily: ensures daily rotation
Line 4 — rotate 10: Save 10 copies of the log file.
Line 5 — missingok: Do not output error if logfile is missing.
Line 6 — notifempty: Donot rotate log file if it is empty.
Line 7 — compress: Compress the old copies of log files with gzip(1) by default
Line 8 — sharedscripts: This makes the scripts to run once, no matter how many logs match the wildcarded pattern, and whole pattern is passed to them.
Line 9 to 11 — postrotate/endscript: The lines between postrotate and endscript (both of which must appear on lines by themselves) are executed after the log file is rotated. These directives may only appear inside a log file definition.
This logrotate utility has many more configuration options. You can get a complete list of those options from its manual page by just running this:
Checking the Logrotation Status
The file «/var/lib/logrotate.status» contains all information about the logrotation status. Hence, to validate the logrotate run status for each configuration file added and verify the status of each one of them, we can run the command below; It will list run time for each config
file.
This will provide you with the latest logrotate status.
We can run a specific logrotate file manually or forcefully by the following command.
Or we can even rotate all the logs in verbose mode with the command below:
Logrotate helps you to manage your log files efficiently and save some disk space by compressing/removing your log files. It may also help you to archive your log files for a future reference by creating an extra copy or by emailing you any newly rotated log files. We can even adjust the configuration to handle each log file daily, weekly, monthly, or when it grows too large. I would recommend using logrotate utility for an easy management of your log files.
Ротация файлов по размеру в logrotate
Написать заметку по настройке ротации логов в logrotate меня побудило то, что постоянно забываю все сделать правильно. Запишу все нюансы, заодно с остальными поделюсь информацией. Речь пойдет о ротации лог файлов по достижении ими определенного размера.
Это будет короткая заметка про конкретную настройку. Подробно описывать работу logrotate не буду, так как в интернете и так полно материала на эту тему.
Для примера буду описывать ротацию логов nginx. После установки nginx, вы получите следующий конфиг для ротации логов — /etc/logrotate.d/nginx.
Все не указанные явно параметры будут браться из дефолтного конфига /etc/logrotate.conf.
Для того, чтобы защитить сервер от заполнения всего свободного пространства диска логами access.log, ротация раз в день не подходит. Тебе за час без напряга смогут забить весь диск логами. Лучше настроить ротацию по достижении определенного размера файла. Для этого вы используете параметр:
И ждете, что по достижении размера файла access.log в десять мегабайт, будет произведена ротация. На самом деле не будет. По-умолчанию, logrotate запускается раз в сутки, поэтому он при всем желании не сможет следить за размером файла и ротировать его чаще, чем раз в сутки.
За его запуск отвечает скрипт в директории /etc/cron.daily/logrotate. Для того, чтобы logrotate мог проверять размер лог файла хотя бы раз в час, скрипт запуска надо перенести в директорию /etc/cron.hourly. А для более частой проверки, добавить его напрямую в cron с нужным интервалом запуска. Например, раз в 5 минут.
Допустим вы все это сделали, но логи все равно не будут ротироваться при достижении заданного размера. Понять, в чем же теперь проблема, не так просто. При запуске logrotate вы не увидите никаких ошибок. Он просто ничего не будет делать. Понять, в чем проблема, можно только при запуске в режиме отладки. Там вы увидите ошибку, если в этот день ротация уже была хотя бы раз.
Смысл тут в том, что logrotate сегодня уже произвел ротацию и создал архив лога с определенным именем и второй раз такой же файл он сделать не может. А маска имени файла при создании настроена в формате %Y%m%d. За эту маску отвечает параметр в /etc/logrotate.conf:
Самый простой вариант — это просто закомментировать этот параметр, тогда все архивы логов будут иметь следующую маску в файлах:
И так далее. Если же вам хочется сохранить исходный формат лога для всех файлов, а для тех, что ротируются по размеру, настроить другую маску имени, используйте дополнительный параметр:
Формат имени архивного лога будет access.log.2019-08-26_15-1566819154.gz. Имена больше не будут дублироваться и logrotate сможет корректно запускать ротацию при достижении указанного размера файла. Обращаю внимание, что формат тут отличается от привычной конструкции в date, к которой обычно все привыкли. Сделать формат %Y-%m-%d_%H-%M не получится. Logrotate не поймет маску с минутами %M. Так что для уникальности имени в пределах одного часа надо использовать %s.
Таким образом, чтобы настроить ротацию лог файла, например, aceess.log, по достижении определенного размера, вам нужно:
- Запускать через cron logrotate с достаточно высокой периодичностью, например раз в час или чаще.
- Настроить маску файла для архива лога, чтобы она была уникальной в каждый момент запуска logrotate.
Вот пример для ротации конфигов nginx или apache по достижении размера лог файла в 10 мегабайт.
Не забудьте создать директорию /var/log/nginx/old для хранения старых логов. На этом у меня все по ротации логов в logrotate с учетом размера файла.
Докеризация nginx и php на сокетах с ротацией логов
Each container should have only one concern
Decoupling applications into multiple containers makes it much easier to scale horizontally and reuse containers. For instance, a web application stack might consist of three separate containers, each with its own unique image, to manage the web application, database, and an in-memory cache in a decoupled manner.
You may have heard that there should be “one process per container”. While this mantra has good intentions, it is not necessarily true that there should be only one operating system process per container. In addition to the fact that containers can now be spawned with an init process, some programs might spawn additional processes of their own accord. For instance, Celery can spawn multiple worker processes, or Apache might create a process per request. While “one process per container” is frequently a good rule of thumb, it is not a hard and fast rule. Use your best judgment to keep containers as clean and modular as possible.
If containers depend on each other, you can use Docker container networks to ensure that these containers can communicate.
В результате обсуждения выяснилось, что можно вместо отправки сигнала USR1 nginx добавить опцию copytruncate в конфигурацию logrotate. Значит в контейнере нет необходимости в запуске нескольких процессов. Однако все действия по настроке запуска ротации логов по cron нужно все равно будет выполнить только не внутри контейнера, а на хосте где работет контейнер. При запуске в одном контейнере и веб-сервер, и ротации логов, отдельная настройка ротации на хосте уже не требуется.
В приведенных выше ссылках даны решения. Впрочем с первого раза все не заработало и пришлось искать причины. Поэтому кроме ссыок я привожу результаты своих опытов. Для того, чтобы можно было познакомиться со способом защиты от DDoS-атак вместо сервера nginx будет запускаться openresty (сборка nginx от Taobao со скриптовым движком Lua). Этот сервер имеет другое по сравнению с nginx расположение каталогов с файлами. Но все остальное абсолютно идентично.
Для начала создадим файл docker-compose.yml в корневом каталоге проекта:
Мы предполагаем что сценарии создания контейнеров будут храниться в файлах docker/php/Dockerfile и docker/nginx/Dockerfile. Имя Dockerfile является именем по умолчанию, следовательно нет необходимости его явно задавать в конфигурации.
Создадим файл docker/php/Dockerfile:
Загружается образ php:7-fpm и создается пользователь с идентификатором заданным параметром UID (в docker-compose.yml UID: 3000) с именем app в группе app. Это нужно чтобы задать права на чтение сокета из контйнера, где будет запущен openresty.
Для того чтобы получить ротацию логов в nginx или openresty, необходимо чтобы контейнер не завершал работу при рестарте веб-сервера, а так же чтобы в этом же контейнере был запущен cron. То есть это не будет однопроцессный контейнер, но иначе ничего не получится. Запускать несколько процессов рекомендуется через supervisor.
Создадим файл docker/nginx/Dockerfile:
Сначала интсаллируются все необходмые программы. Затем копируются конфигурационные файлы из каталога ./docker/nginx/ во внутреннюю файловую систему контейнера. Далее некоторым из этих файлов присваиваются права 644 (в противном случае система не будет выполнять ротацию логов). И также создается пользователь и группа app с тем же самым идентификатором (UID: 3000).
Так же необходмио создать несколько конфигурационных файлов.
Файл docker/php/zz-docker.conf (имя zz-docker.conf присутсвует в конфигурации образа php:7-fpm. Это нигде не описано и может меняться. К сожалению в настоящий момент подробных описаний образов нет, и приходися их исследовать после загрузки из репозитария):
Параметр listen = /sock/docker.sock будет тот же что и в конфигурации nginx.
Основной конфигурационный файл nginx придется переписать т.к. в openresty он не содержит необходимых параметров, а это расположение логов, иднтификатор процесса, пользователь (app), и каталог с конфигурациями виртуалных серверов (/conf.d).
Создадим виртуальный сервер с конфигурацией server.conf:
К прокси обращаемся не через порт, а через сокет unix:/sock/docker.sock .
Теперь создадим файл logrotate.conf:
И задание для cron:
Размер файла size=1k и зспуск ротации каждую минуту (* * * * *) не для рабочего сервера, а тоько для того чтобы можно было при имнимальных временных заратах наблюдать ротацию логов. Команда logrotate копирует логи в архивные файлы. Но пока не будет перезапущен nginx — не произойдет реального создания нового пустого файла логов. Для того чтобы nginx открыл логи заново служит устрашающая команда kill -USR1 `cat /var/run/nginx.pid` .
И наконец конфигурация supervisor:
Совершенно не имеет значения где все эти конфигурационные фйлы находятся, т.к. все пути задаются в операторах COPY из Dockerfile, и в значениях volumes из docker-compose.yml. Теперь нужно набраться терпения и записать все необходимые пути в docker-compose.yml.
Теперь можно добавить скрипты Lua (см. статью на Хабре).