一、printk()的介绍

Linux系统在开机的过程中我们可以看见很多打印信息,这都是Linux内核内部调用printk(level,message)函数打印出来的

其中level是定义的打印优先级,当优先级小于console_loglevel时定义的优先级小于当前日志的打印级别时,信息才会打印在控制终端(根据要打印信息的类型,分为0~7,其中0位最高级别),通常宏来指示日志优先级

#define KERN_EMERG      "<0>"    /* system is unusable */
 #define KERN_ALERT      "<1>"    /* action must be taken immediately */
 #define KERN_CRIT       "<2>"    /* critical conditions */
 #define KERN_ERR        "<3>"    /* error conditions */
 #define KERN_WARNING    "<4>"    /* warning conditions */
 #define KERN_NOTICE     "<5>"    /* normal but significant */
 #define KERN_INFO       "<6>"    /* informational */#define KERN_DEBUG      "<7>"    /* debug-level messages */

其中console_loglevel的初始值是DEFAULT_CONSOLE_LOGLEVEL,可以通过sys_syslog()系统调用进行修改,或者修改文件/proc/sys/kernel/printk下的优先级,,这个文件中包含了4个整数值,分别是当前日志优先级,未明确指定的日志级别时的默认日志优先级,最小允许的日志优先级,引导时的默认日志优先级。向该文件中写入一个整数值,就会把当前日志文件的优先级修改为该值,修改方式为

echo 4 > /proc/sys/kernel/printk(linux内核2.6日志默认的优先级是4)

message是我们要打印出调试的信息

 

二、消息被记录的原理

在内核中有一个内核自定义的一个长度为__LOG_BUF_LEN(在内核配置时为该变量配置值,范围是4kb~1mb)字节ring buffer(循环缓冲区),Linux系统中所有的系统信息输出的信息都是调用printk()都被输出到这里(包含内核信息),

通常获得我们想要的信息,有两种方式,一种是直接读取ring buffer中的信息,另一种是查看/var/log下的文件。

1、直接使用dmesg命令

该命令直接从循环缓冲区中读取数据到stdout

2、通过查看/var/log下的文件

在Linux中有两个守护程序,klogd和syslogd

klogd这个进程会通过syslog()这个系统调用或者读取proc文件系统来得到printk()从ring buffer中得到的信息,也就是我们的内核信息。并且klogd也会把信息传给syslog这个进程的。

LINUX系统启动后,由/etc/init.d/sysklogd先后启动klogd,syslogd两个守护进程,其中syslogd通过/etc/syslog.conf这个配置文件将系统产生的信息分类记录到相应的log中,因此这个目录下会有很多文件,其中将klogd传输过来的内核信息记录到/var/log/messgae中。

 

需要注意的是!!!,syslogd获取内核信息依赖进程klogd,因此要想通过syslogd获得内核的信息,klogd和syslogd这两个守护进程必须同时存在(这时无论当前日志的级别是多少,klogd都会把内核消息输出到/var/log/messgae下。这里我的理解是把打印级别高的输出到控制台,而把所有的内核信息,无论打印级别高低,都输出到/var/log/messgae下),如果klogd没有运行,内核不会传递信息到用户空间,因此此时/var/log/messgae不会有信息,此时只能通过查看内核专门用来存放打印信息的目录/proc/kmsg。

因为循环缓冲区的大小是固定的因此不能无限制的存储日志信息,因此当缓冲区满了之后,printk()函数会从缓冲区的开头,通过覆盖之前的日志信息继续存储最新的信息,这样做会导致原来的信息丢失,但一般之前的信息对我们的调试没什么作用,因此这样做是有利的。

 

为了避免大量的输出信息影响调试,可以通过klogd -f选项指定文件,将信息输出到指定的文件内,或者强制杀死进程klogd,然后打开一个新的终端,使用命令cat /proc/kmsg将信息显示在新打开的终端。

 

一.查看日志方式

命令格式: tail[必要参数][选择参数][文件]

这个是我最常用的一种查看方式
1.tail

-f 循环读取
   -q 不显示处理信息
   -v 显示详细的处理信息
   -c<数目> 显示的字节数
   -n<行数> 显示行数
   -q, --quiet, --silent 从不输出给出文件名的首部 
   -s, --sleep-interval=S 与-f合用,表示在每次反复的间隔休眠S秒

   tail  -n  10   test.log   查询日志尾部最后10行的日志;
   tail  -n +10   test.log   查询10行之后的所有日志;
   tail  -fn 10   test.log   循环实时查看最后1000行记录(最常用的)

   //一般还会配合着grep用, 例如 :  tail -fn 1000 test.log | grep '关键字'
   如果一次性查询的数据量太大,可以进行翻页查看,
   例如:tail -n 4700  aa.log |more -1000 可以进行多屏显示(ctrl + f 或者 空格键可以快捷键)

2.head

head -n  10  test.log   //查询日志文件中的头10行日志;
head -n -10  test.log   //查询日志文件除了最后10行的其他所有日志;

head其他参数与tail 类似

3.cat
cat 是由第一行到最后一行连续显示在屏幕上

一次显示整个文件 : $ cat filename
从键盘创建一个文件 : $ cat > filename  
将几个文件合并为一个文件: $cat file1 file2 > file //只能创建新文件,不能编辑已有文件.
将一个日志文件的内容追加到另外一个 : $cat -n textfile1 > textfile2
清空一个日志文件 $cat : >textfile2

注意:>意思是创建,>>是追加。千万不要弄混了。
cat其他参数与tail 类似

4.tac
tac 则是由最后一行到第一行反向在萤幕上显示出来

5.sed

这个命令可以查找日志文件特定的一段 , 也可以根据时间的一个范围查询

//按照行号
  sed -n '5,10p' filename //这样你就可以只查看文件的第5行到第10行。
  //按照时间段
  sed -n '/2014-12-17 16:17:20/,/2014-12-17 16:17:36/p'  test.log

6.less

less log.log 

shift + G 命令到文件尾部  然后输入 ?加上你要搜索的关键字例如 ?1213

shift+n  关键字之间进行切换

二.其他会应用到的命令

history // 所有的历史记录

history | grep XXX  // 历史记录中包含某些指令的记录

history | more // 分页查看记录

history -c // 清空所有的历史记录

!! 重复执行上一个命令

查询出来记录后选中 : !323

linux日志文件说明

/var/log/message 系统启动后的信息和错误日志,是Red Hat Linux中最常用的日志之一
 /var/log/secure 与安全相关的日志信息
 /var/log/maillog 与邮件相关的日志信息
 /var/log/cron 与定时任务相关的日志信息
 /var/log/spooler 与UUCP和news设备相关的日志信息
 /var/log/boot.log 守护进程启动和停止相关的日志消息
 /var/log/wtmp 该日志文件永久记录每个用户登录、注销及系统的启动、停机的事件