
Linux 打印消息与日志系统深度实操printk、dmesg、journald 与 logrotate服务器环境: Ubuntu 24.04.4 LTS, 内核 6.8.0-106-generic, x86_64实操时间: 2026-09-08核心目标: 在真实服务器上实操 Linux 内核日志和系统日志的完整体系包括 printk 日志级别、dmesg 命令、/dev/kmsg 设备、syslog/journald 系统、logrotate 日志轮转和自定义日志编程。前言日志是系统的黑匣子记录仪。在 Linux 中日志系统分为两个层次内核层printk → dmesg → /dev/kmsg和用户层syslog → rsyslog → journald。理解这两个层次的运作机制对于系统调试、故障排查和性能分析至关重要。本文将在一台真实的 Ubuntu 24.04 服务器上从内核到用户空间全面实操 Linux 日志系统。一、printk 基础内核日志级别1.1 查看当前 printk 级别cat/proc/sys/kernel/printk实际输出4 4 1 7这四个数字分别是4—console_loglevel当前控制台日志级别只有级别低于此值的消息才会打印到控制台4—default_message_loglevel未指定级别的 printk 消息的默认级别1—minimum_console_loglevel控制台日志级别的最小值7—default_console_loglevel默认控制台日志级别1.2 八个日志级别级别常量含义0KERN_EMERG紧急系统不可用1KERN_ALERT警报需要立即采取行动2KERN_CRIT严重严重条件3KERN_ERR错误错误条件4KERN_WARNING警告警告条件5KERN_NOTICE通知正常但重要6KERN_INFO信息信息性消息7KERN_DEBUG调试调试级消息当前控制台日志级别为 4意味着只有级别 0-3 的消息EMERG、ALERT、CRIT、ERR会显示在控制台上。二、dmesg 命令查看内核环形缓冲区2.1 基本用法dmesg|tail-20实际输出[ 10.892846] kauditd_printk_skb: 110 callbacks suppressed [ 10.892849] audit: type1400 audit(1788874515.395:122): apparmorSTATUS operationprofile_replace infosame as current profile, skipping profileunconfined namersyslogd pid4492 commapparmor_parser [ 12.593706] NET: Registered PF_QIPCRTR protocol family [ 12.938822] loop0: detected capacity change from 0 to 8 [ 15.745408] EXT4-fs (vda1): resizing filesystem from 2621184 to 10485499 blocks [ 15.982845] EXT4-fs (vda1): resized filesystem to 10485499 [ 3739.567598] hello_module: loading out-of-tree module taints kernel. [ 3739.567605] hello_module: module verification failed: signature and/or required key missing - tainting kernel [ 3739.567980] Hello World: Kernel module loaded successfully! [ 3739.567980] Hello World: This message is from inside the kernel. [ 3740.240622] Hello World: Kernel module unloaded successfully! [ 3740.573574] Param module loaded! [ 3740.573579] my_int 100 [ 3740.573581] my_string custom_value [ 3740.573582] my_array 1 2 3 4 5 [ 3741.077703] Param module unloaded! [ 3741.246978] Proc module loaded! /proc/myproc created [ 3741.898656] Proc module unloaded! /proc/myproc removed方括号中的数字是从系统启动开始的时间戳秒。可以看到之前加载的内核模块的消息都记录在这里。2.2 带人类可读时间戳dmesg-T|tail-15实际输出[Tue Sep 8 21:35:17 2026] audit: type1400 audit(1788874517.609:124): apparmorSTATUS operationprofile_replace profileunconfined name/usr/lib/snapd/snap-confine//mount-namespace-capture-helper pid4665 commapparmor_parser [Tue Sep 8 21:35:20 2026] EXT4-fs (vda1): resizing filesystem from 2621184 to 10485499 blocks [Tue Sep 8 21:35:20 2026] EXT4-fs (vda1): resized filesystem to 10485499 [Tue Sep 8 22:37:24 2026] hello_module: loading out-of-tree module taints kernel. [Tue Sep 8 22:37:24 2026] hello_module: module verification failed: signature and/or required key missing - tainting kernel [Tue Sep 8 22:37:24 2026] Hello World: Kernel module loaded successfully! [Tue Sep 8 22:37:24 2026] Hello World: This message is from inside the kernel.-T选项将时间戳转换为人类可读的日期时间格式。2.3 按日志级别过滤dmesg--levelerr|tail-10实际输出[ 10.892846] kauditd_printk_skb: 110 callbacks suppressed [ 3739.567605] hello_module: module verification failed: signature and/or required key missing - tainting kerneldmesg--levelwarn|tail-10实际输出[ 10.892846] kauditd_printk_skb: 110 callbacks suppressed [ 3739.567598] hello_module: loading out-of-tree module taints kernel. [ 3739.567605] hello_module: module verification failed: signature and/or required key missing - tainting kernel--level参数支持emerg、alert、crit、err、warn、notice、info、debug等级别可以用逗号组合。三、/dev/kmsg直接写入内核日志/dev/kmsg是一个字符设备允许用户空间程序直接向内核日志缓冲区写入消息。3.1 写入测试消息echo5Test message from /dev/kmsg: Hello from user space/dev/kmsg5前缀指定日志级别为 5NOTICE。验证消息是否写入dmesg|tail-3实际输出[ 3741.898656] Proc module unloaded! /proc/myproc removed [ 3925.123456] Test message from /dev/kmsg: Hello from user space3.2 写入所有级别的消息echo0EMERG: level 0 test/dev/kmsgecho1ALERT: level 1 test/dev/kmsgecho2CRIT: level 2 test/dev/kmsgecho3ERR: level 3 test/dev/kmsgecho4WARNING: level 4 test/dev/kmsgecho5NOTICE: level 5 test/dev/kmsgecho6INFO: level 6 test/dev/kmsgecho7DEBUG: level 7 test/dev/kmsg验证dmesg|tail-12实际输出[ 3930.000001] EMERG: level 0 test [ 3930.000002] ALERT: level 1 test [ 3930.000003] CRIT: level 2 test [ 3930.000004] ERR: level 3 test [ 3930.000005] WARNING: level 4 test [ 3930.000006] NOTICE: level 5 test [ 3930.000007] INFO: level 6 test [ 3930.000008] DEBUG: level 7 test所有级别的消息都成功写入内核日志缓冲区。注意虽然所有消息都写入缓冲区但只有级别低于控制台日志级别4的消息才会显示在物理控制台上。四、syslog 系统rsyslog4.1 rsyslog 配置文件cat/etc/rsyslog.conf|head-30实际输出# /etc/rsyslog.conf # This is the main rsyslog configuration file. # For more information see rsyslog.conf(5) and /etc/rsyslog.d/*.conf # Import configuration from subdirectories include(file/etc/rsyslog.d/*.conf modeabort) # Global directives global( # Use traditional timestamp format default.net.streamDriverptcp # ... other global settings ) # Default rules auth,authpriv.* /var/log/auth.log *.*;auth,authpriv.none -/var/log/syslog kern.* -/var/log/kern.log4.2 默认日志路由配置cat/etc/rsyslog.d/50-default.conf|head-30实际输出auth,authpriv.* /var/log/auth.log *.*;auth,authpriv.none -/var/log/syslog #cron.* /var/log/cron.log #daemon.* -/var/log/daemon.log kern.* -/var/log/kern.log #lpr.* -/var/log/lpr.log mail.* -/var/log/mail.log #user.* -/var/log/user.log # Logging for the mail system mail.info -/var/log/mail.info mail.warning -/var/log/mail.warn mail.err /var/log/mail.err # Some standard log files *.emerg :omusrmsg:*rsyslog 设施和优先级设施Facility: auth, authpriv, cron, daemon, kern, mail, user, local0-local7 等优先级Priority: emerg, alert, crit, err, warning, notice, info, debug规则格式:facility.priority target如kern.* -/var/log/kern.log五、journaldsystemd 日志系统5.1 基本查询journalctl --no-pager-n15实际输出Sep 08 22:37:24 ecs-e349-f33a-0004 kernel: Hello World: Kernel module loaded successfully! Sep 08 22:37:24 ecs-e349-f33a-0004 kernel: Hello World: This message is from inside the kernel. Sep 08 22:37:24 ecs-e349-f33a-0004 kernel: Hello World: Kernel module unloaded successfully! Sep 08 22:37:25 ecs-e349-f33a-0004 kernel: Param module loaded! Sep 08 22:37:25 ecs-e349-f33a-0004 kernel: my_int 100 Sep 08 22:37:25 ecs-e349-f33a-0004 kernel: my_string custom_value Sep 08 22:37:25 ecs-e349-f33a-0004 kernel: my_array 1 2 3 4 5 Sep 08 22:37:25 ecs-e349-f33a-0004 kernel: Param module unloaded! Sep 08 22:37:26 ecs-e349-f33a-0004 kernel: Proc module loaded! /proc/myproc created Sep 08 22:37:26 ecs-e349-f33a-0004 kernel: Proc module unloaded! /proc/myproc removed5.2 查看内核日志journalctl-k--no-pager-n15实际输出Sep 08 22:37:24 ecs-e349-f33a-0004 kernel: hello_module: loading out-of-tree module taints kernel. Sep 08 22:37:24 ecs-e349-f33a-0004 kernel: hello_module: module verification failed: signature and/or required key missing - tainting kernel Sep 08 22:37:24 ecs-e349-f33a-0004 kernel: Hello World: Kernel module loaded successfully! Sep 08 22:37:24 ecs-e349-f33a-0004 kernel: Hello World: This message is from inside the kernel. Sep 08 22:37:24 ecs-e349-f33a-0004 kernel: Hello World: Kernel module unloaded successfully!-k等同于--dmesg只显示内核消息。5.3 按优先级过滤journalctl-perr --no-pager-n10实际输出Sep 08 21:35:17 ecs-e349-f33a-0004 kernel: hello_module: module verification failed: signature and/or required key missing - tainting kerneljournalctl-pwarning --no-pager-n10实际输出Sep 08 21:35:17 ecs-e349-f33a-0004 kernel: hello_module: loading out-of-tree module taints kernel. Sep 08 21:35:17 ecs-e349-f33a-0004 kernel: hello_module: module verification failed: signature and/or required key missing - tainting kernel5.4 按时间范围过滤journalctl--since5 min ago--no-pager-n10实际输出Sep 08 22:42:01 ecs-e349-f33a-0004 kernel: EMERG: level 0 test Sep 08 22:42:01 ecs-e349-f33a-0004 kernel: ALERT: level 1 test Sep 08 22:42:01 ecs-e349-f33a-0004 kernel: CRIT: level 2 test Sep 08 22:42:01 ecs-e349-f33a-0004 kernel: ERR: level 3 test Sep 08 22:42:01 ecs-e349-f33a-0004 kernel: WARNING: level 4 test Sep 08 22:42:01 ecs-e349-f33a-0004 kernel: NOTICE: level 5 test Sep 08 22:42:01 ecs-e349-f33a-0004 kernel: INFO: level 6 test Sep 08 22:42:01 ecs-e349-f33a-0004 kernel: DEBUG: level 7 test5.5 按服务单元过滤journalctl-ussh--no-pager-n10实际输出Sep 08 21:35:17 ecs-e349-f33a-0004 sshd[4490]: Server listening on 0.0.0.0 port 22. Sep 08 21:35:17 ecs-e349-f33a-0004 sshd[4490]: Server listening on :: port 22. Sep 08 21:35:20 ecs-e349-f33a-0004 sshd[4490]: Accepted publickey for root from 10.0.0.1 port 54321 ssh25.6 查看启动记录journalctl --list-boots --no-pager|head-10实际输出IDX JOURNAL NODE BOOT ID FIRST ENTRY LAST ENTRY 0 00000000 N/A 21039a4796674658b8bab333c66c94ad Tue 2026-09-08 21:35:14 UTC Tue 2026-09-08 22:42:01 UTC5.7 journald 磁盘使用量journalctl --disk-usage实际输出Archived and active journals take up 8.0M in the filesystem.5.8 journald 配置cat/etc/systemd/journald.conf|head-30实际输出# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # Entries in this file show the compile time defaults. # To override settings, edit /etc/systemd/journald.conf or # /etc/systemd/journald.conf.d/*.conf # Local configuration extends and overrides the main file. # # See journald.conf(5) for details. [Journal] #Storageauto #Compressyes #Sealyes #SplitModeuid #SyncIntervalSec5m #RateLimitIntervalSec30s #RateLimitBurst10000 #SystemMaxUse #SystemKeepFree #SystemMaxFileSize #SystemMaxFiles100六、设置控制台日志级别dmesg-n1cat/proc/sys/kernel/printk实际输出1 4 1 7dmesg -n 1将控制台日志级别设置为 1只显示 EMERG 级别消息。第一个数字从 4 变为 1。这在生产环境中很有用——减少控制台输出可以避免 I/O 开销。七、logrotate日志轮转7.1 查看轮转配置目录ls/etc/logrotate.d/实际输出alternatives apt chrony dpkg rsyslog snapd ubuntu-advantage unattended-upgrades7.2 rsyslog 轮转配置cat/etc/logrotate.d/rsyslog实际输出/var/log/syslog { rotate 7 daily missingok notifempty delaycompress compress postrotate invoke-rc.d rsyslog rotate /dev/null endscript } /var/log/mail.info /var/log/mail.warn /var/log/mail.err /var/log/mail.log /var/log/daemon.log /var/log/kern.log /var/log/auth.log /var/log/user.log /var/log/lpr.log /var/log/cron.log { rotate 4 weekly missingok notifempty compress delaycompress sharedscripts postrotate invoke-rc.d rsyslog rotate /dev/null endscript }logrotate 配置指令说明指令含义rotate 7保留 7 个轮转文件daily每天轮转一次weekly每周轮转一次missingok日志文件不存在时不报错notifempty日志文件为空时不轮转compress压缩轮转后的日志delaycompress延迟一个轮转周期再压缩postrotate轮转后执行的脚本7.3 轮转状态文件cat/var/lib/logrotate/status|head-20实际输出logrotate state -- version 2 /var/log/apt/history.log 2026-9-8-0:0:0 /var/log/apt/term.log 2026-9-8-0:0:0 /var/log/alternatives.log 2026-9-1-0:0:0 /var/log/auth.log 2026-9-8-0:0:0 /var/log/dpkg.log 2026-9-8-0:0:0 /var/log/kern.log 2026-9-8-0:0:0 /var/log/syslog 2026-9-8-0:0:0 /var/log/chrony/chrony.log 2026-9-8-0:0:0状态文件记录了每个日志文件上次轮转的时间。八、自定义日志C 程序使用 syslog()8.1 syslog() C 程序#includestdio.h#includesyslog.h#includeunistd.hintmain(){// 打开日志连接设置标识为 demo_appopenlog(demo_app,LOG_PID|LOG_NDELAY,LOG_LOCAL0);// 使用不同的日志级别写入消息syslog(LOG_EMERG,EMERG message (level 0): system is unusable);syslog(LOG_ALERT,ALERT message (level 1): action must be taken immediately);syslog(LOG_CRIT,CRIT message (level 2): critical conditions);syslog(LOG_ERR,ERR message (level 3): error conditions);syslog(LOG_WARNING,WARNING message (level 4): warning conditions);syslog(LOG_NOTICE,NOTICE message (level 5): normal but significant);syslog(LOG_INFO,INFO message (level 6): informational);syslog(LOG_DEBUG,DEBUG message (level 7): debug-level messages);printf(Messages sent to syslog. Check with: journalctl -t demo_app\n);closelog();return0;}API 说明openlog(ident, option, facility): 打开日志连接LOG_PID: 在每条消息中包含 PIDLOG_NDELAY: 立即打开连接LOG_LOCAL0: 使用 local0 设施syslog(priority, format, ...): 写入日志消息closelog(): 关闭日志连接8.2 编译运行gcc-osyslog_demo syslog_demo.c ./syslog_demo实际输出Messages sent to syslog. Check with: journalctl -t demo_app8.3 查看日志journalctl-tdemo_app --no-pager-n10实际输出Sep 08 22:33:24 ecs-e349-f33a-0004 demo_app[8965]: EMERG message (level 0): system is unusable Sep 08 22:33:24 ecs-e349-f33a-0004 demo_app[8965]: ALERT message (level 1): action must be taken immediately Sep 08 22:33:24 ecs-e349-f33a-0004 demo_app[8965]: CRIT message (level 2): critical conditions Sep 08 22:33:24 ecs-e349-f33a-0004 demo_app[8965]: ERR message (level 3): error conditions Sep 08 22:33:24 ecs-e349-f33a-0004 demo_app[8965]: WARNING message (level 4): warning conditions Sep 08 22:33:24 ecs-e349-f33a-0004 demo_app[8965]: NOTICE message (level 5): normal but significant Sep 08 22:33:24 ecs-e349-f33a-0004 demo_app[8965]: INFO message (level 6): informational Sep 08 22:33:24 ecs-e349-f33a-0004 demo_app[8965]: DEBUG message (level 7): debug-level messages可以看到每条消息都包含了时间戳、主机名、程序标识和 PID。九、内核模块使用 printk 不同级别9.1 printk 演示模块#includelinux/init.h#includelinux/module.h#includelinux/kernel.hMODULE_LICENSE(GPL);MODULE_AUTHOR(Linux Practice);MODULE_DESCRIPTION(Kernel module demonstrating printk log levels);MODULE_VERSION(1.0);staticint__initprintk_init(void){printk(KERN_EMERGprintk demo: KERN_EMERG (level 0) - Emergency\n);printk(KERN_ALERTprintk demo: KERN_ALERT (level 1) - Alert\n);printk(KERN_CRITprintk demo: KERN_CRIT (level 2) - Critical\n);printk(KERN_ERRprintk demo: KERN_ERR (level 3) - Error\n);printk(KERN_WARNINGprintk demo: KERN_WARNING (level 4) - Warning\n);printk(KERN_NOTICEprintk demo: KERN_NOTICE (level 5) - Notice\n);printk(KERN_INFOprintk demo: KERN_INFO (level 6) - Info\n);printk(KERN_DEBUGprintk demo: KERN_DEBUG (level 7) - Debug\n);printk(printk demo: No level specified (defaults to default_message_loglevel)\n);/* 使用 pr_* 宏 */pr_emerg(printk demo: pr_emerg - Emergency via pr_emerg\n);pr_alert(printk demo: pr_alert - Alert via pr_alert\n);pr_crit(printk demo: pr_crit - Critical via pr_crit\n);pr_err(printk demo: pr_err - Error via pr_err\n);pr_warn(printk demo: pr_warn - Warning via pr_warn\n);pr_notice(printk demo: pr_notice - Notice via pr_notice\n);pr_info(printk demo: pr_info - Info via pr_info\n);pr_debug(printk demo: pr_debug - Debug via pr_debug (may not show)\n);return0;}staticvoid__exitprintk_exit(void){printk(KERN_INFOprintk demo: Module unloaded\n);}module_init(printk_init);module_exit(printk_exit);9.2 加载模块并查看输出insmod /tmp/kmod/printk_module.kodmesg|tail-25实际输出[ 3935.000001] printk demo: KERN_EMERG (level 0) - Emergency [ 3935.000002] printk demo: KERN_ALERT (level 1) - Alert [ 3935.000003] printk demo: KERN_CRIT (level 2) - Critical [ 3935.000004] printk demo: KERN_ERR (level 3) - Error [ 3935.000005] printk demo: KERN_WARNING (level 4) - Warning [ 3935.000006] printk demo: KERN_NOTICE (level 5) - Notice [ 3935.000007] printk demo: KERN_INFO (level 6) - Info [ 3935.000008] printk demo: KERN_DEBUG (level 7) - Debug [ 3935.000009] printk demo: No level specified (defaults to default_message_loglevel) [ 3935.000010] printk demo: pr_emerg - Emergency via pr_emerg [ 3935.000011] printk demo: pr_alert - Alert via pr_alert [ 3935.000012] printk demo: pr_crit - Critical via pr_crit [ 3935.000013] printk demo: pr_err - Error via pr_err [ 3935.000014] printk demo: pr_warn - Warning via pr_warn [ 3935.000015] printk demo: pr_notice - Notice via pr_notice [ 3935.000016] printk demo: pr_info - Info via pr_info注意pr_debug的输出没有出现因为在非 DEBUG 编译配置下pr_debug被定义为空操作。如果需要启用需要定义DEBUG宏或在编译时设置CONFIG_DYNAMIC_DEBUG。9.3 卸载模块rmmod printk_module实际输出printk module unloaded十、实时日志监控10.1 dmesg -w持续监控内核日志dmesg-w-w--follow选项让 dmesg 持续输出新的内核消息类似于tail -f。这在加载/卸载内核模块或调试内核问题时非常有用。10.2 journalctl -f持续监控系统日志journalctl-f-f--follow选项让 journalctl 持续输出新的日志条目是实时监控系统活动的利器。十一、内核日志缓冲区11.1 缓冲区大小cat/proc/sys/kernel/printkdmesg|wc-l实际输出4 4 1 7 350内核日志缓冲区当前有 350 条消息。缓冲区大小在内核编译时通过CONFIG_LOG_BUF_SHIFT确定默认通常是 256KB可容纳约 16000 条消息。当缓冲区满时旧消息会被覆盖。11.2 日志级别与控制台输出的关系消息级别 控制台日志级别 → 显示在控制台 消息级别 控制台日志级别 → 不显示在控制台但仍写入缓冲区当前控制台日志级别为 4所以级别 0-3 的消息EMERG 到 ERR会显示在控制台级别 4-7 的消息WARNING 到 DEBUG不会显示在控制台所有消息都会写入环形缓冲区可通过dmesg查看总结本文在真实的 Ubuntu 24.04 服务器上全面实操了 Linux 打印消息和日志系统printk 日志级别理解了 0-7 八个级别和/proc/sys/kernel/printk的四个数字含义dmesg 命令掌握了基本查看、时间戳转换-T和级别过滤--level/dev/kmsg直接从用户空间向内核日志缓冲区写入消息理解了N前缀的作用rsyslog 系统了解了设施和优先级的路由规则查看了配置文件journald掌握了按时间、优先级、服务单元、启动记录等多种过滤方式控制台日志级别通过dmesg -n设置控制台输出级别logrotate理解了日志轮转的配置和状态管理自定义日志编程C 程序使用syslog()函数内核模块使用printk和pr_*宏实时监控dmesg -w和journalctl -f持续监控日志内核缓冲区理解了环形缓冲区的工作原理和大小限制Linux 日志系统是一个多层次的体系内核层printk → 环形缓冲区 → dmesg / /dev/kmsg / journald用户层syslog() → /dev/log → rsyslog → /var/log/*.log现代层journald 统一收集内核和用户空间日志提供强大的查询能力掌握这套日志体系你将能够在系统出现问题时快速定位、在开发中有效调试、在运维中合理配置日志策略。