分类: LINUX
2013-01-31 00:12:39
日志对于系统的重要性不言而喻,比如对于故障诊断和入侵检测,没有日志几乎寸步难行。Linux系统当中最流行的日志记录器是 ,当前最新版本是 1.5 。
Sysklogd 日志记录器由两个守护进程(klogd syslogd)和一个配置文件(syslog.conf)组成。klogd 不使用配置文件,它负责截获内核消息,它既可以独立使用也可以作为 syslogd 的客户端运行。syslogd 默认使用 /etc/syslog.conf 作为配置文件,它负责截获应用程序消息,还可以截获 klogd 向其转发的内核消息。支持 internet/unix domain sockets 的特性使得这两个工具可以用于记录本地和远程的日志。
内核的控制台日志等级控制哪些内核消息会在控制台上显示。有两种途径可以修改这个等级,不过建议的途径是通过 sysctl 来控制,通常这个设置位于 /etc/sysctl.conf 中。比如:
kernel/printk = 4 4 1 7 安装注意事项下面是 Makefile 文件开头的一部分节选,这部分是在安装是可能需要改动的:
CC= gcc SKFLAGS= $(RPM_OPT_FLAGS) -O3 -DSYSV -fomit-frame-pointer -Wall -fno-strength-reduce # 启用大文件支持,根据你的系统是32位还是64位进行选择 # -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE # -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE # $(shell getconf LFS_SKFLAGS) LDFLAGS= -s # 指定 install 程序的位置 INSTALL = /usr/bin/install # 安装目录 BINDIR = $(prefix)/usr/sbin MANDIR = $(prefix)/usr/share/man # 有bug报告说在一个纯 ELF 系统上需要明确指定连接到 libresolv.a 库。 # 如果你在连接 syslogd 时失败,可以试一试取消下面的注释。 # LIBS = /usr/lib/libresolv.a # 如果你在 ALPHA 平台上连接失败,可以试一试取消下面的注释。 # LIBS = ${LIBS} -linux # 取消下面的注释可以让 klogd 实现启动延迟,这在 klogd 和 syslogd 并行启动或启动顺序靠的非常近的时候很有用。 # KLOGD_START_DELAY = -DKLOGD_DELAY=5 # 下面的定义表示文件位置遵守FSSTND标准。 FSSTND = -DFSSTND # 下面的定义指定了 man page 的宿主和权限。 MAN_USER = root MAN_GROUP = root MAN_PERMS = 644 # 下面的定义指定了 syslogd 守护进程的 .pid 文件名, # 源代码(paths.h)中默认的文件名是"syslog.pid",但很多人认为应当叫"syslogd.pid"。 # 你可以在这里指定你喜欢的名字。 SYSLOGD_PIDNAME = -DSYSLOGD_PIDNAME=\"syslogd.pid\" syslog.confsyslog.conf 是 syslogd 进程的配置文件,将在程序启动时读取,默认位置是 /etc/syslog.conf 。它指定了一系列日志记录规则。规则的格式如下:
facility.level action这个配置文件中的空白行和以"#"开头的行将被忽略。"facility.level"部分也被称为选择符(seletor)。 seletor 和 action 之间使用一个或多个空白分隔。
选择符(seletor)选择符由 facility 和 level 两部分组成,之间用一个句点(.)连接。这两部分将在后面 syslogd 小节中详细描述。下面提到的名字和 /usr/include/syslog.h 中的 LOG_-values 相一致。
facility 指定了产生日志的子系统,可以是下面的关键字之一:
auth 由 pam_pwdb 报告的认证活动。 authpriv 包括私有信息(如用户名)在内的认证活动 cron 与 cron 和 at 有关的信息。 daemon 与 inetd 守护进程有关的信息。 ftp 与 FTP 有关的信息 kern 内核信息,首先通过 klogd 传递。 lpr 与打印服务有关的信息。 mail 与电子邮件有关的信息 mark syslog 内部功能用于生成时间戳 news 来自新闻服务器的信息 syslog 由 syslog 生成的信息 user 由用户程序生成的信息 uucp 由 uucp 生成的信息 local0 ~ local7 由自定义程序使用,例如使用 local5 做为 ssh 功能 * 通配符代表除了 mark 以外的所有功能在大多数情况下,任何程序都可以通过任何 facility 发送日志消息,但是一般都遵守约定俗成的规则。比如,只有内核才能使用"kern" facility 。
level 指定了消息的优先级,可以是下面的关键字之一(降序排列,严重性越来越低):
emerg 系统不可用 alert 需要立即被修改的条件 crit 阻止某些工具或子系统功能实现的错误条件 err 阻止工具或某些子系统部分功能实现的错误条件 warning 预警信息 notice 具有重要性的普通条件 info 提供信息的消息 debug 不包含函数条件或问题的其他信息 none 没有优先级,通常用于排错 * 除了none之外的所有级别facility 部分可以是用逗号(,)分隔的多个子系统,而多个 seletor 之间也可以通过分号(;)组合在一起。需要注意的是,多个组合在一起的选择符,后面的会覆盖前面的,这样就允许从模式中排除一些优先级。
默认将对指定级别以及更严重级别的消息进行操作,但是可以通过下面2个操作符进行修改。
等于操作符(=)表示仅对这个级别的消息进行操作,不等操作符(!)表示忽略这个级别以及更严重级别的消息。这两个操作符可以同时使用,不过"!"必须出现在"="的前面。
动作(action)这个字段定义了对符合条件的消息进行何种操作,可以选择下列操作之一:
普通文件 将消息记录到这个文件中,必须使用绝对路径。如果在文件名之前加上减号(-),则表示不将日志信息同步刷新到磁盘上(使用写入缓存),这样可以提高日志写 入性能,但是增加了系统崩溃后丢失日志的风险。 命名管道 在绝对路径表示的FIFO文件(使用mkfifo命令创建)前加上管道符号(|)即可。通常用于调试。比如:|/usr/adm/debug 终端或者控制台 比如:/dev/tty1 或 /dev/console 远程主机 syslogd 能够将消息发送到远程主机或从远程主机接收消息,不过默认并不转发接收到的消息。要将消息发送到远程主机,可以在主机名前加一个"@"即可。 逗号分隔的用户名列表 critical 级别的消息除了记录到日志之外,通常还转发到root用户。 所有当前登录的用户 如果写上一个星号(*)则表示向当前所有登录的用户显示这条消息。 实例下面的例子来自于实践,希望能够对上面的内容做一个很好的示范以帮助理解。
# 将所有 crit 级别的消息(排除所有内核消息)记录在 critical 文件中 # *.=crit;kern.none /var/adm/critical # 首先记录所有内核消息到 kernel 文件, # crit 级别以上的消息转发到远程同时在本地控制台也显示 # 最后将info(包含)~err(不含)范围的内核消息记录到kernel-info文件(err和更高的级别被忽略) # kern.* /var/adm/kernel kern.crit @finlandia kern.crit /dev/console kern.info;kern.!err /var/adm/kernel-info # 将恰好等于mail.info的消息显示在第12个终端(tcpd默认使用mail.info) # mail.=info /dev/tty12 # 将除mail.info之外的所有mail子系统消息记录到mail文件 # mail.*;mail.!=info /var/adm/mail # 将所有mail.info和news.info消息记录到info文件 # mail,news.=info /var/adm/info # 记录所有info和notice级别的消息,来自mail子系统的除外 # *.=info;*.=notice;mail.none /var/log/messages # 记录所有info级别的消息,来自mail和news子系统的除外 # *.=info;mail,news.none /var/log/messages # 向所有登录用户通知emerg级别的消息 # *.=emerg * # 将所有alert以及更高级别的消息转发到root,joey用户的终端上(如果他们已经登录) # *.alert root,joey # 将所有子系统的所有消息都发送到远程名为"finlandia"的主机 *.* @finlandia syslogdsyslogd 默认通过 /dev/log 这个 unix domain socket 来接收应用程序发送过来的消息,这个位置是由系统的基本C库决定的。
这个程序的命令行参数如下:
syslogd [ -a socket ] [ -f config-file ] [ -h ] [ -l hostlist ] [ -m interval ] [ -n ] [ -p socket ] [ -r ] [ -s domainlist ] [ -v ]参数说明:
-a socket 指定额外需要监听的 socket ,最多指定19个,可以通过修改 syslogd.c 文件中的 MAXFUNIX 宏修改这个默认值。如果你将某些进程在chroot环境下运行,那么这个选项就很有用了。 -f config-file 指定配置文件的位置,默认是 /etc/syslog.conf 。 -h 默认情况下 syslogd 并不转发它接收到的远程主机消息。指定这个选项后,进程将会把它接收到的远程主机消息转发到另一个指定的远程主机。 -l hostlist 指定一个分号(:)分隔的主机名列表,只记录这些主机的 hostname 而不是全限定域名。 -m interval syslogd 默认每隔20分钟产生一个时间戳标记(-- MARK --)。这个选项用于修改这个默认值。设为零将关闭这个特性。 -n 避免自动作为后台进程运行。如果由 init 来直接启动和控制的话这个选项就必须使用。 -p socket 你可以指定一个 unix domain socket 来代替默认的 /dev/log [这个位置是由libc决定的] -r 从 internet domain socket 上接收远程消息,也就是监听从514端口上进来的UDP包。 默认不接受任何远程消息。 -s domainlist 指定一个分号(:)分隔的域名列表,这些域名在记录前都会被剥除。只能指定完整的域名。比如"-s north.de"并不会剥除"satu.infodrom.north.de"的尾巴,你必须这样写才行:在运行时,syslogd 会将自己的进程号保存在 /var/run/syslogd.pid 文件中。所以可以使用下面的命令向运行中的进程发送信号:
kill -信号 `cat /var/run/syslogd.pid` HUP 使得 syslogd 进程重新初始化。所有打开的文件都会被关闭,然后重新读取配置文件,重新开始记录。 TERM 安全退出 CHLD 如果当前正在向所有登录的用户发送消息,那么等待这些子进程结束。 安全问题流氓程序可以通过向 syslogd 进程发送大量日志信息来淹没日志文件或者耗尽磁盘空间。下面是一些建议:
klogd 是一个专门截获并记录 Linux 内核消息的守护进程。其命令行语法如下:
klogd [ -f file ] [ -iI ] [ -n ] [ -o ] [ -p ] [ -s ] [ -k file ] [ -v ] [ -x ] [ -2 ]命令行参数说明:
-f file 将日志直接记录到指定的file中,而不是转发到 syslogd 进程。 -i如果 klogd 将内核消息转发给 syslogd 进程,那么它可以分拣出某些特定的消息。原始内核消息的格式如下:
<[0-7]>Something said by the kernel.尖括号中的数字表示内核消息的优先级,这些数字的定义位于 kernel.h 文件中。当 klogd 收到内核消息之后,将会读取这个数字,并在将此消息转发给 syslogd 时按照这个数字分配适当的优先级。
如果使用 -f 将内核消息直接记录到特定的文件中,那么这条消息将保持原样。
内核地址解析klogd 会尝试将内核地址解析为对应的符号,如果你想得到原始的地址信息,那么可以使用"-2"开关。如果没有使用"-k"选项,那么将会依次尝试下面的路径:
/boot/System.map /System.map /usr/src/linux/System.map因为内核模块动态加载所以地址并不固定,这时就要使用"-i"/"-I"通知 klogd 内核模块的变化。这两个开关都将导致当前正在运行的 klogd 守护进程重新加载内核符号表。应当在每一次加载或者卸载内核模块后立即运行下列命令:
klogd -i-p 开关也可以用于更新内核符号表。它会让 klogd 在检测到保护性错误的时候重新加载内核符号表。使用这个开关需要小心,因为操作系统在出现保护性错误(protection fault)的时候已经变得不稳定了,而 klogd 必须执行系统调用才能重新装载内核符号表,所以这样做可能会导致更糟糕的结果。
控制台日志等级内核默认的控制台日志等级是"7"(debug),也就是等级数字小于等于6的消息(优先级更高)都会显示在控制台上。这些不同等级所代表的意思位 于 kernel.h 文件内,这个包内的 syslog.h 中也有一份拷贝。可以使用 sysctl 来指定控制台日志等级,这通常是在 /etc/sysctl.conf 文件中设置的,比如下面这一行:
kernel.printk = 4 4 1 7就是把内核的控制台日志等级设为了"4"。
信号处理klogd 可以响应8种信号: SIGHUP, SIGINT, SIGKILL, SIGTERM, SIGTSTP, SIGUSR1, SIGUSR2, SIGCONT 。SIGINT, SIGKILL, SIGTERM, SIGHUP 信号会让进程优雅的正常退出。SIGTSTP 信号会让进程停止记录日志并进入休眠状态;SIGCONT 信号会让处于休眠状态的进程重新开始记录日志。组合使用 SIGSTOP 和 SIGCONT 可以在不退出进程的情况下切换日志消息的来源。比如需要卸载 /proc 文件系统的时候,可以使用下面的命令:
# kill -TSTP pid # umount /proc # kill -CONT pidSIGUSR1 和 SIGUSR2 用于加载/重新加载内核符号表。SIGUSR1 表示重新加载内核模块的符号信息;SIGUSR2 表示同时重新加载模块和静态内核的符号信息。如果 System.map 文件位置正确,那么 SIGUSR1 信号将非常有用。特别是在内核模块改变的时候。
相关文件 /proc/kmsg klogd 默认首选的获取内核消息的来源 /var/run/klogd.pid 保存 klogd 的 PID 的文件 /boot/System.map, /System.map, /usr/src/linux/System.map 默认搜索的内核符号表位置
我们可以看到LINUX系统信息日志的途径基本有以下2种:
1>dmesg查看----这个命令比较常见
2>/var/log/下的文件
那下面我们就从这个2个途径着手,一步步的走下去.
<一>
首先,我们来看dmesg这个常见的命令背后隐藏的是什么!!
1> 先让我们来MAN一下这个家伙
从LINUX提供的手册,我们可以得知一条最重要的信息dmesg是从kernel 的ring buffer(环缓冲区)中读取信息的
2> 那什么是ring buffer呢?
在LINUX中,所有的系统信息(包内核信息)都会传送到ring buffer中.而内核产生的信息由printk()打印出来。系统启动时所看到的信息都是由该函数打印到屏幕中。 printk()打出的信息往往以<0><2>...这的数字表明消息的重要级别。高于一定的优先级别会打印到屏幕上, 否则只会保留在系统的缓冲区中(ring buffer)。
至于dmesg具体是如何从ring buffer中读取的,大家可以看dmesg.c源代码.很短,比较容易读懂.
<二>
dmesg怎么搞的大家应该很明白了吧.至于/var/log/下的文件更是大家熟悉得不能再熟悉了!
1> /var/log/..下为什么有这么多文件呢?
一句话解释: 是syslogd这个守护进程根据/etc/syslog.conf,将不同的服务产生的Log记录到不同的文件中.
这里的/etc/syslog.conf我就不细说了,很多这方面的信息(去查吧).
2> 既然知道了,/var/log/..是由syslogd这个守护进程产生的.那就再顺着这条线走下去.
LINUX系统启动后,由/etc/init.d/sysklogd先后启动klogd,syslogd两个守护进程。
其中klogd会通过syslog()系统调用或者读取proc文件系统来从系统缓冲区(ring buffer)中得到由内核printk()
发出的信息.而syslogd是通过klogd来读取系统内核信息.
我想至此,大家心理应该对log产生,读取等一系列的动作有所感觉.
总结一下:
1> 所有系统信息是输出到ring buffer中去的.dmesg所显示的内容也是从ring buffer中读取的.
2> LINUX系统中/etc/init.d/sysklogd会启动2个守护进程:Klogd&&Syslogd
3> klogd是负责读取内核信息的,有2种方式:
syslog()系统调用(这个函数用法比较全,大家去MAN一下看看)
直接的对/proc/kmsg进行读取(再这提一下,/proc/kmsg是专门输出内核信息的地方)
4> Klogd的输出结果会传送给syslogd进行处理,syslogd会根据/etc/syslog.conf的配置把log
信息输出到/var/log/下的不同文件中.