После запуска Rails-приложений полезно настроить автоматическую архивацию (ротацию) файлов журналов (лог-файлов), так как они имеют обыкновение крайне быстро разрастаться до весьма объемных размеров:

$ ls -lh log/production.log
-rw-rw-r-- 1 www-data www-data 193,2M feb 20 17:49 production.log

Найти что-либо в 200-мегабайтном файле не очень просто ;)

Для ротации логов можно использовать стандартный интструмент logrotate. Если его нет в системе, то в случае Debian или Ubuntu его можно просто установить командой:

sudo apt-get install logrotate

В планировщике задач (cron) ежедневно выполняется запуск logrotate /usr/sbin/logrotate /etc/logrotate.conf с указанием файла конфига. В конфиге настраиваются глобальные параметры, которые будут применяться по умолчанию, и как правило подключается директория include /etc/logrotate.d откуда будут подружатся файлы с описанием правил (секции) для конкретных лог файлов. Пример глобального конфига:

create
compress

include /etc/logrotate.d

При ротации логов - текущий log-файл с которым работает программа - удаляется или перемещается, поэтому после ротации лога, будет правильным перезапустить программу/сервис, чей log-файл был удален. Нужно это, что бы программе был сообщен новый дискриптор файла. Хотя это ситуация может разрулится автоматически и без перезагрузки - если такую ситуацию предусмотрели разработчики.

Параметры настройки

Вот список всех параметров на текущий момент:

Параметр Описание
rotate <число> Количество хранимых файлов
daily
weekly
monthly
Производить ротацию раз в день/неделю/месяц
size <байт>
size 1000
size 100k
size 1M
Производить ротацию если log-файл превысил указанный размер
байт
Кбайт
Мбайт
start <число> число с которого начнётся нумерация файлов
compress Архивировать файлы (по умолчанию gzip)
nocompress Отключает compress
delaycompress Не сжимать 'свеже' созданный архив. Например access.log. не будет зжат.
Используется с compress
create <права><владелец><группа>
create root root
После ротации создать пустой log-файл. Любые из этих атрибутов могут быть опущены,
в этом случае вместо них для нового файла будут использованы атрибуты,
имеющие те же значения, что и первоначальный log-файл
nocreate Не создавать файл
copy Создать копию оригинального log-файла, не изменяя его. Исключает create
nocopy Отключает copy
copytruncate Создать копию оригинального log-файла, а потом его 'обнулить'.
Таким образом сам файл не удаляется.
Исключает copy, create
ifempty Архивирует даже пустой файл (используется по умолчанию)
notifempty Не архивировать пустые файлы
missingok В случае отсутствия оригинального log-файла не вызовет ошибку
nomissingok В случае отсутствия оригинального log-файла вызовет ошибку
postrotate
<команды>
endscript
Строки, находящиеся между postrotate и endscript
будут выполнены как sh скрипт после архивирования log-файла
prerotate
<команды>
endscript
Аналогично postrotate, только действия будут выполнены до начала архивирования
sharedscripts Скрипты postrotate и prerotate будут выполнены только один раз в рамках своей секции.
nosharedscripts Отключает sharedscripts.
Скрипты будут выполняются при ротации каждого log-файла,
при определение /var/log/apache2/*.log скрипт будет выполнен столько раз
сколько уникальных log-файлов будет находится в данной директории
olddir <путь>
olddir /home/logs
Перемещать архивные файлы в указанную директорию
noolddir Отключает olddir
dateext К имени файлов журналов добавляется дата (%Y%m%d), вместо номера
su <user> <group> Выполняется с правами указанного пользователя. Необходимо если ошибка: "because parent directory has insecure permissions", т.е. на директорию с логами, есть право на запись кроме root'a

Пример настройки logrotate

Создаём файл конфигурации logrotate для Rails-приложения /etc/logrotate.d/rails_example_com (настройки для нескольких приложений можно хранить в одном файле, но более правильно использовать по одному файлу на приложение). Содержание файла должно быть примерно такое:

/path/to/rails/app/log/*.log {
daily
missingok
rotate 7
compress
delaycompress
notifempty
copytruncate
}

Запуск

Параметры запуска

Параметр Описание
-d debug - отладочный режим.
В режиме отладки не будут производиться изменения в log-файле и файле состояния
-f
--force
Принудительно произвести ротацию, даже если в данный момент она не требуется
-m <команда>
--mail <команда>
Указать команду для отправки почты.
Команда должна принимать два аргумента: тема сообщения и адрес получателя.
Текст письма передается стандартным вводом (stdin).
По умолчанию /usr/bin/mail -s
-s <файл>
--state <файл>
Указать куда записать файл состояния.
Что - то типа лога, показывает последнюю дату когда производилась ротация
(если создания архива не требуется правилами, то дата все ровно обновляется)
По умолчанию /var/lib/logrotate/status

Для проверки работы можно запустить logrotate с параметром -d (отладка), благодаря которому logrotate покажет, как он будет работать, но ничего не изменит:

sudo logrotate -d /etc/logrotate.d/rails_example_com

Если logrotate в тестовом режиме отработал без ошибок, то можно ждать, когда он отработает автоматически на следующие сутки или запусить его вручную:

sudo logrotate -f /etc/logrotate.d/rails_example_com

Также, можно второй раз вручную запустить logrotate, чтобы убедиться, что опция delaycompress работает, результатом двух запусков logrotate должно быть следующее:

ls
production.log production.log.1 production.log.2.gz

Что мы видим:

  • production.log — остался на месте, пуст и доступен для записи для приложения;
  • production.log.1 — копия логов между первым и вторым запуском logrotate;
  • production.log.2.gz — сжатый лог за всё предыдущее время.

С указанными настройками каждый день будет проходит архивация лог-файла, будут храниться логи за последние 7 дней и каждый день будет удаляться самый старый лог. Каждому архивному файлу присваивается номер, чем больше номер тем ‘старее’ архив.

Варианты настроек

В предложенном ниже файле настройки для хранения журналов за последний год с еженедельной архивацией:

/path/to/rails.example.com/tmp/log/*.log {
weekly
missingok
rotate 52
compress
delaycompress
notifempty
copytruncate
}

Ротация логов Апача:

/var/log/apache2/*.log {
weekly
missingok
rotate 52
compress
delaycompress
notifempty
create 640 root adm
sharedscripts
postrotate
# Скрипт на перезагрузку Апача
if [ -f "`. /etc/apache2/envvars ; echo ${APACHE_PID_FILE:-/var/run/apache2.pid}`" ]; then
/etc/init.d/apache2 reload > /dev/null
fi
endscript
}