LE Blog

Инженер с поэтической душой

05.11.2010 firtree_right Ротация логов рельсового приложения

hay roller

Введение

Это уже давно известная тема, и я не претендую на открытие Америки, но для себя зафиксирую это знание.

Даже если вы используете капистрано для выкладывания проекта в сеть, логи приложения хранятся в одном и том же месте (папка shared/log и разрастаются до огромных размеров. Можно, конечно, запускать после каждого обновления файлов проекта комманду:

rake log:clear

Но есть более цивилизованные методы. Тем более, после определённого времени код проекта начинает обновляться всё реже и реже.

С помощью системы

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

Чтобы организовать это удовольствие для своего проекта нужно создать файл /etc/logrotate.d/my_project:

/path/to/my_project/shared/log/*.log {
  weekly
  missingok
  rotate 10
  nomail
  compress
  delaycompress
  sharedscripts
  postrotate
    touch /path/to/my_project/current/tmp/restart.txt
  endscript
}

Здесь написано:

  1. weekly — разбивать лог еженедельно;
  2. missingok — не выходить с ошибкой, если файла нет;
  3. rotate 10 — хранить 10 предыдущих томов;
  4. nomail — не высылать удаляемые тома на электронную почту;
  5. compress — архивировать;
  6. delaycompress — архивировать не сразу, т.к. после переименования файла и до перезапуска пэссенджера логи пишутся в тот же переименованный файл;
  7. sharedscripts — запускать скрипт один раз для всех логов по маске;
  8. postrotate...endscript — скрипт, который нужно запустить после ротации: в данном случае перезапустить пэссенджер.

Файлом должен владеть root:root. Теперь можно проверить и запустить принудительно, убедившись, что наш файл включается в общий список:

sudo logrotate -dv /etc/logrotate.conf
sudo logrotate -fv /etc/logrotate.conf

С помощью руби

В руби есть встроенный метод ротации логов. Достаточно в файе config/environment.rb написать внутри блока Rails::Initializer.run один из вариантов:

config.logger = Logger.new(config.log_path, "weekly")

или

config.logger = Logger.new(config.log_path, 10, 1.megabyte)

Первый вариант осуществляет ротацию раз в неделю, а второй — по достижении файлом размера в 1 мегабайт и хранит 10 старых томов. Только в данном случае архивацию, если она нужна, придётся организовывать отдельно.

Было бы интересно

Для логротейт можно написать такую маску, которая бы включала в себя все логи всех рельсовых проектов. Но мне неизвестен способ потом написать такой скрипт, который бы перезапускал именно те проекты, для которых была сделана ротация. Например, если логротэйт не нашёл нужного файла, то и скрипт не запустит. А если мы указываем путь типа /path/to/*/shared/.log, то и скрипт должен перебирать все эти проекты и создавать или просто менять дату редактирования файлов restart.txt. Или можно просто перезапускать апач.

Материалы для самостоятельного изучения

  1. Документация logrotate (по-русски)
  2. Что ещё можно делать с логами приложения на рельсах