日志文件管理

本文以Log File Management一文(案例操作系统为Gentoo Linux)为基础进行翻译整理,结合Red Hat Linux以及实践的经验记载。

System Logger

system logger是一个服务,允许不同的软件工具通过一个统一标准的接口来记录程序事件。对于本地运行的程序,这些工具可以通过/dev/log socket。远程服务则可以童工网络发送事件。

/dev/log

/dev/log是由系统日志程序(system logger)创建的可以被所有人写入的。每个工具都希望通过系统日志程序的socket来简单记录日志。这个系统日志程序在socket的另一头监听并处理程序发送过来的日志事件。

日志事件元信息(Log Event Meta Information)

当工具需要记录一个日志是,需要提供两个附加字段信息:

  • 事件相关的类型(facility)

这里facility是指发送事件的程序类型。这样系统日志程序能够过滤消息,也可以将消息发送到不同的日志文件。例如,类型有authpriv(安全/认证消息),cron(定时执行的消息)和kern(内核消息)。完整的消息类型可以使用 man 3 syslog查询。

  • 事件的重要程度

重要程度

说明

DEBUG

调试目的的消息

INFO

信息类的消息

NOTICE

一个常规但是比信息类更重要的消息

WARNING

需要注意的警告信息

ERROR

错误消息需要进一步干预

CRIT

当关键错误发生时,常规操作可能被中断或者运行在降级模式

ALERT

警报,需要立即采取行动

EMERG

系统不可用

系统日志配置

这里的案例是syslog-ng日志程序,配置文件是 /etc/syslog-ng/syslog-ng.conf ,这个文件的配置非常直观,以下是案例配置

@version: 3.0
options {
  stats_freq(43200);
};

source src {
  unix-stream("/dev/log" max-connections(256));
  internal();
  file("/proc/kmsg");
};

destination messages { file("/var/log/messages"); };
destination cron { file("/var/log/cron.log"); };
destination auth { file("/var/log/auth.log"); };

filter f_messages { not facility(cron, auth, authpriv); };
filter f_cron { facility(cron); };
filter f_auth { facility(auth, authpriv); };
filter f_sys_app            { facility(local0,local1,local2,local3,local4); };

filter f_warnplus { level(warn, err, crit, emerg); };

log { source(src); filter(f_cron); filter(f_warnplus); destination(cron); };
log { source(src); filter(f_auth); destination(auth); };
log { source(src); filter(f_messages); destination(messages); };
log { source(src); filter(f_sys_app);         flags(final); };
log { source(src); destination(d_sys_loghost); };
  • source部分定义消息的来源,然后filter部分定义了过滤器,以及destination定义消息存储的文件位置

  • filter部分定义了消息的过滤方式,例如f_warnplus指接收warn以及以上重要级别的信息

  • source部分定义了系统日志管理器从哪里接收消息,这里/dev/log socket表示接收本地通过socket传送的消息,另外还接收内核消息接口kmsg和它自己的内部日志

logger工具

logger是一个shell工具,可以提供脚本方式向系统日志管理程序发送日志事件进行记录,以下是一个简单案例

ping 192.168.0.1 | logger -it logger_test -p local3.notice &

注意,上述命令会将消息记录到 /var/log/messages中类似如下

Apr 27 00:39:27 example-server logger_test[27478]: PING 192.168.0.1 (192.168.0.1) 56(84) bytes of data.
Apr 27 00:39:27 example-server logger_test[27478]: 64 bytes from 192.168.0.1: icmp_seq=1 ttl=255 time=1.45 ms
Apr 27 00:39:28 example-server logger_test[27478]: 64 bytes from 192.168.0.1: icmp_seq=2 ttl=255 time=1.03 ms
Apr 27 00:39:29 example-server logger_test[27478]: 64 bytes from 192.168.0.1: icmp_seq=3 ttl=255 time=1.60 ms

详细使用方法参考 man logger

/proc/kmsg/dev/log

内核日志(使用printk()功能)发送消息给内核空间的ring buffer。这些消息有两种方式可以被用户空间应用程序访问:通过/proc/kmsg文件(需要/proc已经挂载),以及通过sys_syslog系统调用。

有两个主要的应用程序来读取(某种程度是控制)内核的ring buffer:dmesgklogd。前者是用户打印出ring buffer中内容,后者是一个daemon服务,用来从/proc/kmsg中读取消息(如果/proc没有挂载就调用sys_syslog)并发送这些消息给syslogd或控制台。

在用户空间,有一个syslogd是一个监听在Unix domain socket的服务,并且可以选择让它监听在514的UDP端口。这个日志服务也可以从klogd来接收消息(syslogd不使用/proc/kmsg),然后将这些消息写入日志文件,或者命名管道,或者发送到远程主机(通过syslog协议,在514 UDP端口)。可以通过/etc/syslog.conf配置。

用户空间应用程序通常使用libc的功能syslog来记录消息日志。libc发送这些消息到Unix domain socket /dev/log (可以被syslogd读取)。不过,如果应用程序是使用chroot运行则消息会写入到其他socket,例如/var/named/dev/log。此时,要配置syslogd来监听这些特定位于/dev/logsocket。

syslog协议只是一个电报协议(datagram protocol),没有办法阻止一个应用程序发送syslog数据给任何Unix domain socket(只要它被允许打开socket),这样就完全绕开了libcsyslog功能。如果这些数据是符合syslogd格式的,就会使用这些数据来记录日志。

新型的rsyslogsyslog-ng已经取代了传统的syslogd,并且提供了通过加密的TCP连接将消息发送给远程主机,以及提供高可靠的时间戳。此外,systemd也具备自己的日志机制,

使用Logrotate维护日志

很多工具并没有提供日志轮转功能或日志清理功能,此时可以使用logrotate来管理日志。这个工具通过cron定时触发,并通过独立分离的配置文件来管理配置

这里的案例是 /etc/logrotate.d/syslog-ng

/var/log/messages /var/log/secure /var/log/maillog /var/log/spooler /var/log/boot.log /var/log/cron /var/log/kern{
        rotate 6
        monthly
        missingok
        sharedscripts
        postrotate
                /etc/rc.d/init.d/syslog-ng reload 2>/dev/null || true
        endscript
}
  • rotate 6monthly表示以每月为基础轮转6次(也就是可以保留7个月历史记录),旧日志文件会添加一个时间戳到文件名

  • missingok表示如果日志文件不存在也是ok的

  • sharescripts表示上面这些需要处理的日志文件都完成轮转之后在执行postrotate部分工作

  • postrotate表示轮转结束以后执行的命令,也就是syslog-ng重新加载配置和日志文件

logrotate配置参数

参数

功能

compress

通过gzip 压缩转储以后的日志

nocompress

不需要压缩时,用这个参数

copytruncate

用于还在打开中的日志文件,把当前日志备份并截断

nocopytruncate

备份日志文件但是不截断

create mode owner group

转储文件,使用指定的文件模式创建新的日志文件

nocreate

不建立新的日志文件

delaycompress

和 compress 一起使用时,转储的日志文件到下一次转储时才压缩

nodelaycompress

覆盖 delaycompress 选项,转储同时压缩。

errors address

专储时的错误信息发送到指定的Email 地址

ifempty

即使是空文件也转储,这个是 logrotate 的缺省选项。

notifempty

如果是空文件的话,不转储

mail address

把转储的日志文件发送到指定的E-mail 地址

nomail

转储时不发送日志文件

olddir directory

转储后的日志文件放入指定的目录,必须和当前日志文件在同一个文件系统

noolddir

转储后的日志文件和当前日志文件放在同一个目录下

prerotate/endscript

在转储以前需要执行的命令可以放入这个对,这两个关键字必须单独成行

postrotate/endscript

在转储以后需要执行的命令可以放入这个对,这两个关键字必须单独成行

daily

指定转储周期为每天

weekly

指定转储周期为每周

monthly

指定转储周期为每月

rotate count

指定日志文件删除之前转储的次数,0 指没有备份,5 指保留5 个备份

tabootext [+] list

不转储指定扩展名的文件,缺省的扩展名是:.rpm-orig .rpmsave

size size

当日志文件到达指定的大小时才转储,可以指定bytes(缺省)以及KB(sizek)或者MB (sizem).

/etc/cron.daily/logrotate配置了每天由cron程序调用一次logrotate

简单删除旧日志的方法

如果不想使用logrotate来管理日志,而是仅仅想简单地删除超过一个月的旧日志,可以配置一个cron定时任务。例如 /etc/cron.weekly/elog-cleanup

#!/bin/sh

find /var/log/portage/elog -type f -mtime +30 -exec rm '{}' \;

参考

Last updated