printk、dmesg、rsyslog相关知识总结
printk是内核日志打印的函数。
如果编译内核时选择了CONFIG_PRINTK=y,则会增加这个功能,否则所有printk都会被替换成空语句。
不过放心,当前suse和euler都已经开启了这个选项。
1、日志源
printk的实现是将字符串格式化之后,拷贝到全局环形缓冲区 log_buf 中。
用户态程序可以使用syslog(type=2 or 3 or 4)系统调用从内核环形缓冲区中读取这个日志。
rsyslog从/proc/kmsg中持续读取(通过select来poll),并写入/var/log/messages文件(通过/etc/rsyslog.conf配置)。
dmesg从/dev/kmsg中读取。
cat /dev/kmsg可以获得和dmesg几乎同样的效果,区别是命令最后会阻塞住等待新日志并持续打印。
通过修改系统配置 echo off > /proc/sys/kernel/printk_devkmsg 可以禁止从 /dev/kmsg 文件读取。
有三个可选值 on、off、ratelimit,默认是 ratelimit。
也可以通过系统启动参数 printk.devkmsg=on 或者 printk.devkmsg=off 来控制。
不过这样的话,/proc/sys/kernel/printk_devkmsg就无法被修改了。
2、内核日志环形缓冲区大小
默认内核日志环形缓冲区大小是编译内核时通过CONFIG_LOG_BUF_SHIFT宏进行控制的。
suse配置的18(1<<18=256KB),euler配置的20(1<<20=1MB)。
通过系统启动参数log_buf_len=n,可以设置内核日志环形缓冲区大小为n字节。
通过系统启动参数nmi_log_buf_len=n,可以设置内核在nmi上下文打印日志时使用的环形缓冲区大小为n字节。
3、日志级别
printk 有八个日志优先级,分别是 0 KERN_EMERG、1 KERN_ALERT、2 KERN_CRIT、3 KERN_ERROR、4 KERN_WARNING、5 KERN_NOTICE、6 KERN_INFO、7 KERN_DEBUG。
系统配置文件 /proc/sys/kernel/printk 记录了四个日志级别相关的参数,对应内核变量console_printk。
int console_printk[4] = {
DEFAULT_CONSOLE_LOGLEVEL, // 日志级别小于这个值,就打印到console上
DEFAULT_MESSAGE_LOGLEVEL, // 当使用 printk(KERN_DEFAULT) 打印日志的时候,就使用这个loglevel
MINIMUM_CONSOLE_LOGLEVEL, // console日志级别最小值
DEFAULT_CONSOLE_LOGLEVEL, // 默认console日志级别
};
和日志级别相关的内核启动参数有
1、debug(将console loglevel设置为10)
2、quiet(将console loglevel设置为4)
3、loglevel=n(将console loglevel设置为n)
在/etc/rsyslog.conf中,有个配置项$klogConsoleLogLevel配置为1,所以rsyslog会把/proc/sys/kernel/printk第一个值改为1 。因此默认只有KERN_EMERG的日志会打印在console上。
rsyslog从/proc/kmsg读取,是直接从内核日志缓冲区读取的。根据/etc/rsyslog.conf,一般来说所有的内核日志都会打印到/var/log/messages。
dmesg从/dev/kmsg读取,也是直接从内核日志缓冲区读取的,所以所有内核日志都能通过dmesg查看。
有一个例外,将在动态debug日志部分讲到。
4、动态debug日志
如果使用printk(KERN_DEBUG)打印日志,不叫动态debug日志(我们先称为静态debug日志)。
通过pr_debug或者dynamic_pr_debug打印的日志,才叫动态debug日志。
默认情况下,静态debug日志通过dmesg是可以查看的,动态debug日志是看不到的。
开启动态debug日志特性,需要在内核编译的时候选择CONFIG_DYNAMIC_DEBUG=y。
如果没有打开这个特性,pr_debug或者dynamic_pr_debug都不会有任何打印。
suse和euler都已打开此特性。
这个编译选项不控制静态debug日志。通过printk(KERN_DEBUG)打印的日志,默认是能够通过dmesg和/var/log/messages看到的。
而动态debug日志默认不打印。内核提供了配置文件/sys/kernel/debug/dynamic_debug/control来单独控制每个debug日志是否能够打印。
具体可以参考内核文档【suse】Document/dynamic-debug-howto.txt,或者【euler】Documentation/admin-guide/dynamic-debug-howto.rst,或者3ms链接 http://3ms.huawei.com/km/blogs/details/5523725。
5、日志流控
如果你发现一个日志频繁打印影响了系统性能,那可能需要增加日志流控。
通过带_ratelimited后缀的日志函数打印日志(如printk_ratelimited、pr_emerg_ratelimited_ratelimited、pr_alert_ratelimited、pr_crit_ratelimited、pr_err_ratelimited、pr_warn_ratelimited、pr_notice_ratelimited、pr_info_ratelimited、pr_debug_ratelimited等),是可以做到日志流控的。
控制策略是默认写死的,每5秒(DEFAULT_RATELIMIT_INTERVAL)最多打印10条日志(DEFAULT_RATELIMIT_BURST)。
END
- 点赞
- 收藏
- 关注作者
评论(0)