Удобную штуку всё таки придумали — лог-файлы. Всегда можно «вернуться в прошлое» и отыскать нужное событие. Особенно полезными лог-файлы оказываются при всякого рода расследованиях: причин нестабильности работы какого-нибудь демона или даже попыток несанкционированного проникновения в систему. Однако частенько бывает так, что «курить логи» администратор начинает уже слишком поздно, когда система пришла в нерабочее состояние. А ведь в большинстве случаев неприятному событию предшествует громкое «кричание» системы в лог-файлах, на которое если вовремя среагировать, можно много чего предотвратить. Конечно же, ежедневное рассматривание содержимого лог-файлов системы — занятие нереальное и глупое, особенно если объёмы логов составляют не пять строчек, да и что нам, время девать некуда? В сегодняшней заметке речь пойдёт об известной многим администраторам  автоматическом просмотрщике логов logwatch.

Задачей logwatch является избавить вас от необходимости создавать велосипеды в области автоматического анализа лог-файлов. Являясь модульной по своей архитектуре, утилита предоставляет вам возможность легко (если знаете Perl) расширять перечень анализируемых типов лог-файлов. Перечень же типов лог-файлов, которые logwatch умеет анализировать «из коробки», впечатляет: начиная от /var/log/messages и заканчивая логами CISCO-оборудования. Результаты анализа утилита группирует и помещает в отчёт, который может как выводиться в stdout, так и отправляться электронной почтой. Формат отчёта предлагается в двух вариантах: plaintext или HTML, при этом вы можете регулировать уровень детализации отчёта исходя из собственных потребностей.

Установка

Установить утилиту можно либо из исходников, либо же пользуясь штатным менеджером пакетов, благо logwatch присутствует в репозиториях всех популярных дистрибутивов. В Ubuntu/Debian утилита легко устанавливается командой:

# apt-get install logwatch

В процессе установки из пакета в Debian/Ubuntu logwatch автоматически не создаёт нужного ей для хранения временных файлов каталога /var/cache/logwatch, и вам необходимо сделать это самостоятельно:

# mkdir /var/cache/logwatch

Файлы конфигурации logwatch по умолчанию находятся в /usr/share/logwatch, и если вы намерены редактировать какой-либо из них, то делать это нужно не с оригинальным файлом, а с его копии, размещённой в каталоге /etc/logwatch.

Настройка

Основной файл конфигурации logwatch находится в /usr/share/logwatch/default.conf/logwatch.conf и прежде, чем редактировать, скопируйте его:

# cp /usr/share/logwatch/default.conf/logwatch.conf /etc/logwatch/conf/

Файл logwatch.conf очень хорошо само-документирован и настолько прост, что у вас не должно быть сложностей с его исправлением.  Среди опций, обычно затрагиваемых при конфигурации, можно отметить следующие:

  • LogDir — путь к каталогу, в котором программа будет искать файлы, обычно это /var/log;
  • TmpDir — путь к каталогу, в котором утилита будет размещать временные файлы. По умолчанию это /var/cache/logwatch, который мы с вами создали ранее;
  • Output — указывает программе метод вывода отчёта. Может быть: stdout (в поток стандартного вывода), mail (почтовым сообщением) или file (в файл);
  • Format — определяет формат отчёта. Может иметь значение text или html;
  • MailTo — определяет адрес получателя отчёта, если Output = mail;
  • MailFrom — определяет адрес отправителя отчёта, если Output = mail;
  • Filename — задаёт путь к файлу отчёта, если Ouput = file;
  • Archives — используется для указания утилите необходимости анализа не только текущих лог-файлов, но и архивных (например messages.1, messages.2.gz и т. п.). Принимает значения Yes или No;
  • Range — за какой период времени отбирать анализируемые сообщения: All, Today или Yesterday;
  • Detail — определяет уровень детализации отчёта. Может принимать как числовые значения от 0 (минимум детализации) до 10 (максимум). Также можно использовать синонимы: Low, Med и High, которые соответственно равны числовым 0, 5 и 10;
  • Service — этот параметр указывает программе имя службы, логи которой необходимо анализировать. Может иметь значение All или имя службы (имя файла из каталога /usr/share/logwatch/scripts/services/). Если необходимо анализировать логи более одной службы, но не всех, то опцию Service следует определить несколько раз с указанием имён нужных служб, по одной за раз. Если же необходимо анализировать лог-файлы всех служб, кроме некоторых, то необходимо сначала определить Service = All, а затем перечислить мена ненужных служб, предварив их знаком «минус», например: Service = «-zz-network»;

Настраиваемые параметры анализатора для каждой службы  можно найти в /usr/share/logwatch/default.conf/services, а пути размещения лог-файлов каждой службы — в /usr/share/logwatch/default.conf/logfiles. Обычно значений параметров, определённых в этих файлах, достаточно для корректной работы, если в вашей системе все файлы хранятся в каталогах по умолчанию и имеют стандартные имена. Если же у вас в системе некоторые файлы расположены в специфических местах, то вам следует указать logwatch, где их искать. Рассмотрим на примере лог-файлов Apache, конфигурация для которого расположена в файле /usr/share/logwatch/default.conf/logfiles/http:

########################################################
#   Define log file group for httpd
########################################################
 # What actual file?  Defaults to LogPath if not absolute path....
LogFile=httpd/*access_log
LogFile=apache/*access.log.1
LogFile=apache/*access.log
LogFile=apache2/*access.log.1
LogFile=apache2/*access.log
LogFile=apache2/*access_log
LogFile=apache-ssl/*access.log.1
LogFile=apache-ssl/*access.log

# If the archives are searched, here is one or more line
# (optionally containing wildcards) that tell where they are...
#If you use a "-" in naming add that as well -mgt
Archive=archiv/httpd/*access_log.*
Archive=httpd/*access_log.*
Archive=apache/*access.log.*.gz
Archive=apache2/*access.log.*.gz
Archive=apache2/*access_log.*.gz
Archive=apache-ssl/*access.log.*.gz

# Expand the repeats (actually just removes them now)
*ExpandRepeats
# Keep only the lines in the proper date range...
*ApplyhttpDate

Как видим, logwatch использует опцию LogFile для определения маски имён лог-файлов, и опцию Archive — для маски архивов. Обратите внимание, что маски файлов указываются относительно каталога, определённого в опции LogDir основного файла конфигурации.  Допустим, у вас есть отдельный каталог для хранения логов Apache, скажем, для отдельного домена. В этом случае необходимо скопировать файл /usr/share/logwatch/default.conf/logfiles/http.conf в /etc/logwatch/conf/logfiles и добавить в него несколько строк:

LogFile=apache2/mydomain.com/access.log
LogFile=apache2/mydomain.com/access.log.1
Archive=apache2/mydomain.com/access.log.*.gz

Запуск

После того, как файлы конфигурации готовы и проверены, достаточно лишь запустить утилиту:

# logwatch

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

$ls-l/etc/cron.daily/*logwatch*

— rwxr-xr-x1root root268Mar  4  2011/etc/cron.daily/00logwatch

Удачного вам анализа!

Если ведением логов занимается демон syslog, то их ротацией — утилита newsyslog.

Демон syslog работает постоянно, и запускается при старте системы. Утилита newsyslog — запускается по cron-у, раз в час — если не указано иначе:

# cat /etc/crontab | grep log
# Rotate log files every hour, if necessary.
0       *       *       *       *       root    newsyslog

Настройки ротации логов хранятся в файле /etc/newsyslog.conf, к примеру:

# logfilename          [owner:group]    mode count size when  flags [/pid_file] [sig_num]
/var/log/all.log                        600  7     *    @T00  J
/var/log/amd.log                        644  7     100  *     J
/var/log/auth.log                       600  7     100  *     JC

Тут:

logfilename — обязательный параметр, полный путь к файлу лога, который необходимо проверять;
owner:group — необязательный параметр, владелец/группа, которой принадлежит файл;
mode — права доступа к файлу;
count — сколько копий заархивированных файлов хранить;
size — предельный размер файла лога в килобайтах, после которого он будет заархивирован и создан новый, для указания «любой размер» — установите *;
when — время в часах, через которое файл будет заархивирован, даже если его размер не превысил заданный в size, что бы игнорировать опцию — установите *;
flags — флаги:

  • B — по умолчанию, newsyslog добавляет в новый лог-файл сообщение о том, что лог-файл был ротирован, но если лог-файл бинарный, то это сообщение испортит лог, с параметром B newsyslog не будет добавлять никаких сообщений в лог;
  • C — если лог-файл не существует, то его необходимо создать;
  • G — если указан данный флаг, то в названии лог-файла можно использовать стандартные шаблоны (например *);
  • J — сжимать лог-файл, используя bzip2;
  • N — не предупреждать никакой процесс, о ротации лог-файла;
  • W — если используются флаги Z или J, то newsyslog должен подождать, пока завершится процесс архивации;
  • Z — сжимать лог, используя gzip.

Далее:

[/pid_file] – необязательный параметр, определяющий путь к файлу, в котором хранится PID процесса приложения, работающего с данным логом. Если он указан, то приложение будет оповещено о ротации посылкой сигнала, на что оно должно произвести соответствующие действия со своей стороны;
[sig_num] – необязательный параметр, определяющий номер сигнала, посылаемый приложению при ротации, чтобы произошло переоткрытие нового лог-файла для записи. По умолчанию используется SIGHUP, т. е. «1» (в обычных случаях посылается с помощью kill -1 или kill -HUP). Некоторые демоны для переоткрытия лог-файлов требуют другого номера сигнала, как например, для nginx, php-fpm, sphinx нужен SIGUSR1, т. е. «30».

Теперь — добавим новую запись в настройку newsyslog.

Сначала — создадим файл, который будет ротироваться:

# touch /var/log/somesite.access.log

Установим ему размер в 10Кб:

# truncate -s 10240 /var/log/somesite.access.log

Проверим:

# ls -hl /var/log/somesite.access.log
-rw-r--r--  1 root  wheel    10k Feb  1 12:55 /var/log/somesite.access.log

Теперь — добавляем новую строку в файл /etc/newsyslog.conf:

/var/log/somesite.access.log            600  7     1 *    ZC

Запустим newsyslog с ключём -n — в таком случае он не будет выполнять ротацию, а только отобразит — какие действия будут выполнены:

# newsyslog -n
/var/log/somesite.access.log <7Z>: trimming
rm -f /var/log/somesite.access.log.7
rm -f /var/log/somesite.access.log.7.gz
rm -f /var/log/somesite.access.log.7.bz2
rm -f /var/log/somesite.access.log.7.xz
ln /var/log/somesite.access.log /var/log/somesite.access.log.0
chmod 600 /var/log/somesite.access.log.0
mktemp /var/log/somesite.access.log.zXXXXXX
chmod 600 /var/log/somesite.access.log.zXXXXXX
mv /var/log/somesite.access.log.zXXXXXX /var/log/somesite.access.log
Signal all daemon process(es)...
kill -1 64569           # /var/run/syslog.pid
Compress all rotated log file(s)...
gzip /var/log/somesite.access.log.0
chmod 600 /var/log/somesite.access.log.0.gz

И запустим newsyslog с ключём -v для подробного режима:

# newsyslog -v
Processing /etc/newsyslog.conf
/var/log/all.log <7J>: does not exist, skipped.
/var/log/amd.log <7J>: does not exist, skipped.
/var/log/auth.log <7J>: size (Kb): 32 [100] --> skipping
...
/var/log/somesite.access.log <7Z>: size (Kb): 10 [1] --> trimming log....
Signal all daemon process(es)...
Notified daemon pid 64569 = /var/run/syslog.pid
Pause 10 seconds to allow daemon(s) to close log file(s)
Compress all rotated log file(s)...

Посмотрим на файл теперь:

# ls -hl /var/log/ | grep somesite
-rw-------  1 root      wheel      74B Feb  1 13:00 somesite.access.log
-rw-------  1 root      wheel     148B Feb  1 13:00 somesite.access.log.0
-rw-------  1 root      wheel     144B Feb  1 12:58 somesite.access.log.1.gz

Готово.

Примечание: Размещать файлы логов можно в любой директории — хоть в /home пользователя, newsyslog обработает их в любом случае.

Возникла необходимость перенести ZFS систему на другой диск, теории начитался, но ни одного «боевого» решения не нашел.
За оказанную помощь при решении вопроса большой салам засылается taurus'у c iXBT.
Попытаюсь расписать подробнее, чтобы было меньше вопросов у народа.

Имеем рабочий диск:

# uname -a
FreeBSD 8.2-RELEASE FreeBSD 8.2-RELEASE #0 r219081M: Wed Mar  2 08:29:52 CET 2011
root@www4:/usr/obj/usr/src/sys/GENERIC  amd64
# gpart show
=>       34  976773101  ada0  GPT  (466G)
34        128    1  freebsd-boot  (64K)
162    8388608    2  freebsd-swap  (4.0G)
8388770  104857600    3  freebsd-zfs   (50G)
113246370  863526765           - free -  (412G)

системный пул myboot находится на 3-ей партиции

# zfs list
myboot           4.33G  44.6G    21K  none
myboot/root      4.33G  44.6G  3.93G  /
myboot/root/tmp   228K  44.6G   228K  /tmp
myboot/root/var   344M  44.6G   301M  /var

У меня был новый 2.5' HDD 60gb, в системе отбился как ad1
Создаем GPT разметку:

# gpart create -s GPT ad1
ad1 created

создаем загрузочный партишн:

# gpart add -s 128k -t freebsd-boot -l boot ad1
ad1p1 added

4Gb партишн для swap:

# gpart add -b 290 -s 4g -t freebsd-swap -l swap ad1
ad1p2 added

и партишн для системы:

# gpart add -t freebsd-zfs -l data ad1
ad1p3 added

#

gpart show
=>       34  117208060  ad1  GPT  (56G)
34        256    1  freebsd-boot  (128K)
290    8388608    2  freebsd-swap  (4.0G)
8388898  108815100    3  freebsd-zfs   (52G) 

в boot записал gptzfsboot-загрузчик и protective MBR:

# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ad1
boot added ad1

создал пул zroot для системы на новом HDD:

# zpool create -m /mnt zroot /dev/gpt/data

делаем снимок старой системы:

# zfs snapshot -r myboot@2013-01-14

(ключ -r — рекурсивный снимок всех дочерних FS)

# zfs list -t snapshot
NAME                         USED  AVAIL  REFER  MOUNTPOINT
myboot@2013-01-14               0      -    21K  -
myboot/root@2013-01-14      59,1M      -  3,93G  -
myboot/root/tmp@2013-01-14    53K      -   228K  -
myboot/root/var@2013-01-14  42,8M      -   297M  -

передаем данные со старого пула в новый на этой же машине:

# zfs send -vR myboot@2013-01-14 | zfs receive -vFd zroot

либо подключаем новый HDD на другой машине,
предварительно загрузившись с LiveCD и на старой системе выполняем:

# zfs send -vR myboot@2013-01-14 | ssh 192.168.x.x zfs receive -vFd zroot

где 192.168.x.x — IP 2-ой машины
теперь, либо выключаем 1-ый комп и меняем старый HDD на новый, либо
продолжаем на 2-ой машине.
Грузимся с LiveCD, затем
монтируем пул в /mnt и прописываем кэш файл:

# zpool import -o cachefile=/tmp/zpool.cache -o altroot=/mnt zroot
# cp /tmp/zpool.cache /mnt/boot/zfs
# zfs list
NAME              USED  AVAIL  REFER  MOUNTPOINT
zroot           4.33G  44.6G    21K  none
zroot/root      4.33G  44.6G  3.93G  /mnt
zroot/root/tmp   228K  44.6G   228K  /mnt/tmp
zroot/root/var   344M  44.6G   301M  /mnt/var
# echo 'zfs_enable="YES"' >> /mnt/etc/rc.conf
# echo 'zfs_load="YES"' >> /mnt/boot/loader.conf
# echo 'vfs.root.mountfrom="zfs:/zroot/root"' >> /mnt/boot/loader.conf

либо проверяем их наличие

# cat /mnt/boot/loader.conf | more
# cat /mnt/etc/rc.conf | more

перемонтируем FS

# zfs unmount -a
# zpool set cachefile='' zroot
# zfs set mountpoint=legacy zroot/root
# zfs set mountpoint=/var zroot/root/var
# zfs set mountpoint=/tmp zroot/root/tmp
# zpool set bootfs=zroot/root zroot
# reboot

Все, после ребута система нормально прогрузилась с нового HDD.