logrotate Lighttpd

Несколько месяцев тому назад встал вопрос о ротации логов веб-сервера Lighttpd.
В гугле традиционно везде советовали logrotate, ok, скачал – не понравилось, насколько помню дефолтный конфиг предпологал рестарт веб-сервера после ротации логов, возможно конфиг можно было и допилить, но.. зачем тогда logrotate вообще нужен, если его надо допиливать?
|=> apt-get purge logrotate
Сейчас хотел посмотреть заново те дефолтные конфиги logrotate, да вот незадача, похоже пакет обновился и теперь конфигов-примеров вообще нет. Ну и хрен с ним.

Чем дело закончилось думаю понятно, написал скрипт, он находит в папке логи и копирует их с добавлением даты в имя, а в оригиналы посылает echo с датой и временем, тем самым обнуляя их – ВСЁ, и никаких рестартов/релоадов Lighttpd.

——————————–

Added 2011.04.19 08:12 PM: Заметка про logrotate в Ubuntu 10.*

В 10.* Убунтах logrotate идёт “из коробки”, набор сриктов для ротации расположен в /etc/logrotate.d/, в частности там лежит файл lighttpd, который ротирует логи в /var/log/lighttpd/*.log и после ротации как Вы думаете что он делает?

/etc/init.d/lighttpd reload > /dev/null 2>&1

За это я поплатился полторами часами даунтайма веба на днях, благо это было 7 утра. От части конечно мой косяк, был подключён тестовый домен, но lighty видно по запарке [после переезда на 10LTS] забыли перезапустить, как оказалось не было нужных прав для новых логов. Но сам факт, если бы этот перезапуск делался в ручную – вы бы сразу увидели/проконтролировали всё ли прошло нормально.
Так что просто удалите файл /etc/logrotate.d/lighttpd дабы избежать произвольных ребутов веб-сервера.

——————————–

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

Вторая версия скрипта уже сама находила логи и подавала tar’у, теперь при появлении новых логов в каталоге у пользователя скрипт в редактировании не нуждался, но.. код дублировался для каждого пользователя.

Что же делать? Правильно, нужно основной код ротации загнать в функцию, что я и сделал в последней версии скрипта.

Теперь если мне надо добавить очередую папку логов нового пользователя, я просто добавляю в конец скрипта строку с вызовом фунции и передаю ей три аргумента: ‘имяпользователя’, ‘путь до логов пользователя’, ‘путь куда сохранить архив с логами’.

Собственно сам скрипт с примерами использования:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#!/bin/bash
# Author: LeoN @ka Children of koRn
# www.muscari.icarrot.rocks / XMPP: ChildrenofkoRn@muscari.icarrot.rocks
# iLAB – Time to fly
### logrotate lighttpd ###
### Version script V06 of 2011.03.15 AM 09:18 AM ###
# глобальные переменные:
PLOG='/root/Lighty.logrotate.txt'
LSROT="## Last logrotate: "`date +%Y"."%m"."%d" "%I":"%M" "%p`" ##"
#####
echo '\n'`date +%I":"%M":"%S" "%p`" # logrotate: start script"'\n'
# записываем дату ротации в лог tar'a
echo '\n'$LSROT >> $PLOG
# собственно сама функция ротации логов
rotate ()
{
# список аргументов, которые нужно передать функции при вызове слева - направо, по порядку:
# $1 - имя пользователя, используется в имени архива, строки 42, 45
# $2 - путь до каталога логов пользователя, строка 23
# $3 - путь до каталога, куда будет сохранён архив, строки 42, 44, 45
#
# переходим в каталог с логами
cd "$2"
# получаем список файлов, фильтруем grep'ом по ".log", Sed преобразует список в одну строку,
# ну и записываем результат в локальную переменную $a
local a="`ls | grep ".log" | sed ':a;N;s/\n/ /;ta'`"
# переменная с датой, которая добавится к именам копий логов
local cpdate="`date +%y%m%d_%I%M%p`"
# поиск логов в текущем каталоге и копирование с переименованием их
for file in *.log; do
  cp $file `basename "$file" .log`_$cpdate.log
done
# далее обнуляем логи, посылая echo c датой и временем ротации
# утилита tee может дублировать вывод stdout в несколько файлов, причем как дописывать в них, так и переписывать, скармливаем ей список из переменной $a.
local lasttime="## Last logrotate: `date +%Y"."%m"."%d" "%I":"%M":"%S" "%p` ##"
echo $lasttime | tee $a > /dev/null
# упаковка и удаление исходных файлов tar'ом
# "test -d $3 || mkdir -p $3 && tar ..." -
# проверяем существует ли папка $3, если нет - создаём и только потом запускаем tar
# опция --remove-files удаляет исходные файлы после упаковки
# список файлов получаем из переменной $a, предварительно делаем замену Sed'ом '.log' на '_$DATE.log'
# " >> $PLOG 2>&1" перенаправляем вывод stdout и stder tar'a в лог $PLOG, при успешной упаковке в лог запишутся только имена упакованных файлов
local tardate="`date +%y%m%d_%I%M%p`"
test -d $3 || mkdir -p $3 && tar czvf "$3/lighttpd_$1_$tardate.tar.gz" --remove-files `echo $a | sed "s/\.log/_$cpdate\.log/g"` >> $PLOG 2>&1
# устанавливаем для папки с архивами права только на чтение для пользователя.
chown root:root $3 && chmod 750 $3
echo `date +%I":"%M":"%S" "%p`" # logrotate completed for $1 > $3/lighttpd_$1_$tardate.tar.gz"
# завершение функции
return 0
}
#####
# вызовы функции с параметрами, ниже идут три примера непосредственно самой ротации.
#
# ротация логов /var/log/lighttpd, третий аргумент 'logrotate#save', т.е. архив будет сохранён в подкаталоге с логами, т.е. в '/var/log/lighttpd/logrotate#save'
rotate 'var' '/var/log/lighttpd' 'logrotate#save'
# ротация логов для пользователя solo
rotate 'solo' '/home/solo/logs' 'logrotate#save'
# ротация логов для пользователя fess, в этот раз мы передаём функции полный путь до каталога с архивами, т.к. надо сохранить не в подкаталоге c логами
rotate 'fess' '/home/fess/logs' '/home/fess/data/save'
#
echo '\n''All operations completed, bye!''\n'
# завершение работы скрипта
exit 0

Download Lighty.logrotate.sh by LeoN version V06 of 2011.03.15 AM 09:18 AM

## скрипт тестировался на Lighttpd версии 1.4.19-4ubuntu2 и Ubuntu 9.04 Jaunty, а также в Ubuntu 10.10 Maverick ##

Строки 13 и 47, 61 с echo служат чисто для мониторинга при ручном прогоне скрипта, при добавлении скрипта в cron их лучше закомментировать.
Добавляем скрипт в cron от рута, например, у меня он запускается каждое первое число месяца в 4:15 утра:

crontab -e -u root
# добавляем строку с нашим скриптом '15 4 1 * * sh /root/Lighty.logrotate.LeoN.V06.sh'

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

Если кому-то нужно исключить какие-то файлы из обработки, то нужно отредактировать 26 строку скрипта [например добавить ещё один grep с исключениями] и строки 30-32, где происходит копирование логов с переименованием.

Со строками 30-32 нужно подумать, например добавить условие проверки дополнительное или привязать копирование к списку получаемого из переменной $a.

# так будут копироваться только те файлы, которые находятся в списке $a
# это всего лишь эскиз, но работать должен
for file in `echo $a`; do
  cp $file `basename "$file" .log`_$cpdate.log
done

26 строку скрипта можно легко реорганизовать, например так:

local a="`ls | grep ".log" | grep -v -E -i -w 'error|ftp|somename' | sed ':a;N;s/n/ /;ta'`"

будут исключены файлы, которые содержат в имени части: error, ftp, somename.
или

local a="`ls | grep ".log" | grep -v "/old.log" | sed ':a;N;s/n/ /;ta'`"

будут исключён подкаталог /old.log, хотя подкаталоги и так откидываются первым grep, посему этот пример для общего развития.

На самом деле скрипт небольшой и занимает около 20 строк, если выкинуть все комментарии.


Я не стал нагружать скрипт проверкой локальной переменной $a, т.е. если tar’у будет подан пустой аргумент вместо списка файлов, т.к. максимум что произойдёт – не создаться пустой архив и скрипт перейдёт к следущему вызову функции по спику, т.е. продолжит ротацию других каталогов.


Ограничение скрипта: чтобы имена файлов, которые будут ротироваться не содержали пробелов – иначе они будут просто пропущены.
Хотя, думаю и это можно допилить при желание тем же sed’ом (;

Единcтвенная заминка при составлении скрипта для меня был вопрос:
Как sed’ом преобразовать вывод списка от ls в одну строку, разделяя строки пробелом?
Отвечаю:

# используем sed
sed ':a;N;s/n/ /;ta' input.txt > output.txt
# или через paste
paste -s -d " " input.txt > output.txt
# можно через tr, объединяет, но пробелы между строками не добавляет
tr -d 'n' input.txt > output.txt


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

Ссылка по смежной теме: Установка Lighttpd+MySQL+PHP+PHPMyAdmin в Ubuntu


—-
Публикация данной статьи на других ресурсах допускается только при указании автора статьи – Children of koRn и ссылки на оригинал.

Кстати, на нашем сервере работает XMPP сервере Ejabberd на домене muscari.icarrot.rocks, все желающие могут присоединиться, регистрация доступна через веб – тут. Enjoy!