概述
有的時候運作linux核心的裝置(現在市場上有很多智能裝置運作android或GNU/Linux)發生了當機、挂起或其他不正常的行為,但是該裝置并沒有連接配接控制台序列槽,如何擷取核心log就需要這些工具了,核心可能發生過oops,通過這些工具可以檢視發生錯誤的具體内容,幫助進行問題診斷。
下面簡單介紹一下擷取核心log工具的原理和使用。
0x1 klogd&syslogd
0x11 klogd
klogd是一個專門截獲并記錄 Linux 核心消息的守護程序,可以指定輸出到控制台,檔案或syslogd守護程序等,常用情況是把核心消息輸出到syslogd程序,由syslogd統一處理。
0x12 syslogd
syslogd負責記錄系統中kenel或應用程式(郵件、新聞等)産生的各種log資訊的工具。這些資訊被寫入到系統檔案中,通常是/var/log目錄下,或者是輸出到遠端server,讓使用者進行故障排除、追蹤嘗試非法入侵的使用者等等。
本文主要關注的是核心log,syslogd涉及到的log資訊種類很多,并且都有對應等級描述,配置檔案syslog.conf需要用規定的文法進行配置,内容比較多,這裡不做過多介紹,要更詳細了解syslogd及配置方法,請參考https://linux.die.net/man/8/syslogd。
klogd擷取核心log通過兩種方式,一種是系統調用syslog(),glibc對應用程式的API是klogctl(),兩個函數的原型分别為:
int syslog(int type, char *bufp, int len);
#include <sys/klog.h>
int klogctl(int type, char *bufp, int len);
另一種方式是,通過/proc/kmsg,以正常打開檔案形式,通過系統調用open、read、write去操作。
klogd輸出到syslogd的方法是通過glibc中的api,openlog 、syslog 、closelog,這幾個函數的原型是:
#include <syslog.h>
void openlog(const char *ident, int option, int facility);
void syslog(int priority, const char *format, ...);
void closelog(void);
内部操作都是通過socket實作,其中會在調用openlog的時候建立socket,調用syslog的時候實作發送,調用closelog關閉socket。需要了解更多,請參考glibc源碼。
0x14 利用klogd&syslogd儲存核心log
系統初始化時打開守護程序:
在/etc/inittab檔案中指定控制台序列槽裝置後添加如下指令:
# 啟動klogd syslogd服務
null::respawn:/sbin/klogd -n
null::respawn:/sbin/syslogd -n
# 重新開機系統之前關閉
null::shutdown:/bin/killall klogd
null::shutdown:/bin/killall syslogd
注意: 在init控制klogd和syslogd的情況下-n參數一定要加,否則會執行完之後直接退出,init程序會反複重新開機這兩個守護程序。
syslogd配置儲存核心消息
syslogd的配置檔案/etc/syslog.conf添加核心log的配置
kern.* -/var/log/kern.log
上面配置的解釋:kern是核心log的關鍵字,表示需要處理核心log, *是表示要儲存所有級别的log, -代表每次有log寫入要同步檔案到磁盤,/var/log/kern.log是儲存log的路徑名稱。
0x15 klogd在嵌入式系統中和PC中的差別
通常在嵌入式系統中由busybox提供系統工具,klogd也在其中,它支援兩個選項c 和n:
-c 設定控制台消息的預設等級,核心消息等級由0到7,定義在核心代碼的kern_levels.h頭檔案中
-n 上面已經解釋過,由init程序控制klogd時要加上
而PC端的klogd要強大很多,可以輸出到檔案、動态配置核心log來源、動态加載核心符号表等幫助分析核心錯誤,例如oops。但是現在很多PC端的GNU/Linux系統發行版中已經不用klogd和syslogd了,它們已經被功能更強大的rsyslog服務所去取代。
0x2 dmesg
列印或控制kernel ring buffer,預設的行為是顯示所有儲存在kernel ring buffer中的log資訊。
0x21 常用指令選項
-c 清除log
當完成列印顯示後清除kernel ring buffer的内容。
-s 定義緩沖區大小
定義指定大小的緩沖區用于查詢kernel ring buffer。預設大小為 16392(核心3.16 log buffer大小是16384位元組),如果你設定了一個大于預設值的緩沖區,那就可以用這來檢視完整的kernel ring buffer内容,下限是4096位元組,如果比這個值小則改為4096。
-n 設定log級别
設定控制台輸出log級别。比如,-n 1或-n alert選項阻止了除了核心panic資訊之外的其他所有資訊在控制台列印。所有級别的log資訊仍然可以通過/proc/kmsg檔案中擷取,是以,syslogd(8)同樣可以用來對資訊的輸出進行控制。當使用-n選項時,dmesg不會列印和清除kernel ring buffer中的内容。
-r
列印原始資料,也就是不加消息級别字首
要注意真正的原始資料依賴于讀取核心日志的方法。/dev/kmsg與系統調用syslog()不同。為了向後相容,dmesg傳回syslog的資料格式。也可以通過/dev/kmsg讀取,例如,使用指令:
dd if=/dev/kmsg iflag=nonblock
0x22 dmesg擷取核心log以及輸出原理
dmesg 的核心消息來源有兩個,其中一個是系統調用syslog,和klogd是相同的,調用glibc的klogctl接口實作。
另一個是通過裝置檔案/dev/kmsg擷取,通過系統調用open、read、write去操作dmesg通過擷取核心log後,通過fwrite函數輸出到stdout。
0x23 dmesg與x86中dmesg的差別
1. busybox中隻支援-c -n -s -r四個選項;
2. buxybox 日志緩沖區最小是16k,最大是16M, x86最小是4096+8,沒有設定上限;
3. busybox隻支援通過syslog系統調用讀取核心日志,x86支援syslog系統調用和/dev/kmsg。
0x24 使用方法
終端指令行下輸入指令
dmesg | less
dmesg | grep keyword
0x3 核心log在klogd dmesg中的資料流
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0NXYFhGd192UvwVe0lmdhJ3ZvwFM38CXlZHbvN3cpR2Lc1TPB10QGtWUCpEMJ9CXsxWam9CXwADNvwVZ6l2c052bm9CXUJDT1wkNhVzLcRnbvZ2Lc1TPn10dBRVTzg2MjZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39DO1IDOwETM4EDOwMDM3EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
圖 核心log輸入輸出流
0x4 klogd和dmesg的共同點和差別
共同點:
1. 都是擷取核心消息到使用者空間;
2. 都可以通過系統調用syslog擷取核心log;
3. 它們通過所有方法擷取的核心log都是kernel ring buffer中的内容。
差別:
klogd輸出log資訊到檔案或syslogd程序中,比較适用于無人值守的情況,當系統發生過挂起,或裝置發生過斷電重新開機,log仍然可以完好的儲存。
dmesg擷取log後輸出到stdout,也就是終端螢幕或控制台序列槽,比較适用于實時檢視kenrel ring buffer中的内容,比如事先并沒有連接配接控制台,或核心log優先級設定的數字很低(優先級很高),或是log早已被其他應用程式繁多的log所淹沒的情況下(android系統log很多)使用,通過dmesg仍然看以檢視核心log。當然現在的ubuntu發行版中也儲存了dmesg資訊到檔案中,但是rsyslog已經儲存了核心log,對這個行為表示不了解。
參考資料:
klogd
http://www.linuxcommand.org/man_pages/klogd8.html
http://baike.baidu.com/link?url=DNO3mDsSEUT7pju2ujw9-WxT–wmxp4yAwCHayIBQLjya_O4d1BiBj8cdyeUyuSNwXIhCJWC7l0XYj_LHPpgy_
syslogd
https://linux.die.net/man/8/syslogd
dmesg
http://man7.org/linux/man-pages/man1/dmesg.1.html
核心源碼位址:
https://www.kernel.org/
linux工具源碼位址:
https://www.kernel.org/pub/linux/utils/util-linux/
glibc源碼位址
http://ftp.gnu.org/gnu/glibc/
busybox源碼位址
https://busybox.net/downloads/