作者 主題: [已解決] 使用 busybox 的 syslogd, klogd 如何做訊息的過濾?  (閱讀 14979 次)

0 會員 與 1 訪客 正在閱讀本文。

andrew

  • 實習板主
  • 懷疑的國中生
  • **
  • 文章數: 69
    • 檢視個人資料
Hi all:

我想在我的嵌入式系統中弄個syslog的機制,
我使用busybox提供的syslogd和klogd,
關於這方面目前我所認知的是:

(1)使用syslog()函數可以讓一般的Application將message紀錄到
   /var/log/messages中, 但是syslogd必須要啟動, 否則訊息不會被寫入/var/log/messages中.

(2)使用printk()函數可以讓Kernel Module把訊息紀錄到/var/log/messages中,
   但是syslogd和klogd都必須先啟動, 否則訊息不會被寫入/var/log/messages中.

---

但是因為我又不想紀錄太多的訊息, 所以我想詢問的是要怎麼對訊息做過濾,
關於這方面目前我所認知的是:

(1)使用syslog()函數時可以設定level, 關於level的定義如下:

   0: LOG_EMERG
   1: LOG_ALERT
   2: LOG_CRIT
   3: LOG_ERR
   4: LOG_WARNING
   5: LOG_NOTICE
   6: LOG_INFO
   7: LOG_DEBUG

例如, 如果我在Application中寫了這樣的程式碼:
syslog(LOG_NOTICE, "System Message - Notice");
syslog(LOG_INFO, "System Message - Info");

syslogd啟動後執行, 會在/var/log/messages中看到下面兩項訊息:

Jan  1 00:00:50 Hostname syslog.notice System log daemon exiting.
Jan  1 00:00:50 Hostname syslog.info System log daemon exiting.

(2)使用printk()函數也可以設定level, 定義如下:

   0: KERN_EMERG, 系統無法使用
   1: KERN_ALERT, 必須立即執行
   2: KERN_CRIT, 緊急狀態
   3: KERN_ERR, 錯誤狀態
   4: KERN_WARNING, 警告狀態
   5: KERN_NOTICE, 正常狀態且十分重要
   6: KERN_INFO, 報告
   7: KERN_DEBUG, debug-level訊息

例如, 我寫了一個簡單的kernel module,
再insmod時會 printk("<4>Hello, World\n");

若klogd和syslogd"同時啟動"(我測試的結果似乎兩個都要啟動?)
insmod之後會在/var/log/messages中看到:
Jan  1 00:39:38 Hostname user.warn kernel: Hello, World

---

我想做的事情就是做過濾, 比如說我只想讓syslogd 紀錄
LOG_ERR以上的層級(就是只顯示0~3的層級) <== 對一般Application而言
KERN_ERR以上的層級(就是只顯示0~3的層級) <== 對kernel事件而言

要如何做到呢?

---

另外, 我還發現一件詭異的事情, 測試這兩個case時,
如果使用remote logging (指令: syslogd -R <ip>)
我發現application的訊息可以被傳到遠端,
但是kernel module所紀錄的訊息只能被紀錄在target端, 無法傳送到遠端!
不知道是什麼原因, 有人試過嗎?

---

OK~以上是我目前的測試和認知, 如果各位也有開發過syslog的話,
請給我一點建議和觀念上的指證, 謝謝!
« 上次編輯: 2009-09-23 06:50 由 andrew »
find /my_brain type sleepy -exec rm -rf {} \;

netman

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 17465
    • 檢視個人資料
    • http://www.study-area.org
我對 library 等級的呼叫沒甚麼概念.
不過, 若是用 logger 命令的話, 除了你前面提到的 level 外, 還要指定 facility 的.

如果只針對 level, 不知道可否修改 syslog.conf:
*.err /var/log/messages
我的理解這是 err 及"以上", 也就是 err-emerg 之間.
而你所提的"以上", 似乎是我理解的"以下"...

andrew

  • 實習板主
  • 懷疑的國中生
  • **
  • 文章數: 69
    • 檢視個人資料
引述: "netman"
若是用 logger 命令的話, 除了你前面提到的 level 外, 還要指定 facility 的.

如果只針對 level, 不知道可否修改 syslog.conf:
*.err /var/log/messages


Hi 陳老師:

其實我曾經是你在台南的學生(感謝您)...哈哈!

這個問題已經解決了, 最近有時間才把它整理上來,

因為我們的 syslogd 和 klogd 都是使用 busybox 套件提供的,
而且通常我們都不使用 config file 來做,
而是直接寫在 code 裡面, 你說的 logger 我有去看過,
不過在編譯 busybox 的時候, 我們預設並沒有編譯進去,
所以我的方向就變成一定要從修改程式碼著手,

我在網路上查到的資訊告訴我:

撰寫 kernel module 時使用的 printk() 函數可以丟出核心的訊息
你可以打 dmesg 看到那個訊息, 測試的方法就是去寫個測試的 module,
然後在 init_module() 和 cleanup_module() 時分別以 printk() 印出字串,
例如: test.o, insmod test.o 時和 rmmod test 時都會印出字串,
這些字串都可以用 dmesg 看到.

另外, printk()可以傳參數指定 LEVEL,
例如: printk("<1>Hello");
      printk("<3>Hello");
分別指定 KERN_EMERG 和 KERN_ERR 等級(參考: man 2 syslog)


關於 syslogd 和  klogd 的運作概念, 我喜歡看這一個網頁上的圖,
參考: http://www.rhce.com.tw/rhel/syslog/index.html
它很清楚的說明之間的關係, 透過 printk() 所印出的訊息會先丟給 klogd,
klogd 再傳給 syslogd 然後紀錄到 /var/log/message.
一般的應用程式(APP)也可以透過設定檔, 委託 syslogd 紀錄到 /var/log/message,
或是自行撰寫程式碼將訊息紀錄到 /var/log/message.

所以, 如果我要對核心的訊息做 filter, 我要處理的 "那一段" 應該是
klogd --> syslogd 的這一段.

我在網路上看到的第二個資訊就是, 如果你同啟動 klogd, 和 syslogd,
不管你的level設定是什麼, 所有的核心訊息都會紀錄到 /var/log/message 中.
事實上在一般的 PC 上或是使用預設的 busybox 都是如此,
但是當我看過原始碼之後, 發現一切都是程式碼在作祟.

打開 busybox 的  klogd.c, 可以看到下面這段 code:

static void doKlogd(...)
{
   ...

   syslog(priority, "%s", message);

   ...
}

如果你去 search 'syslog' 的字串, 你會發現它呼叫了幾個這樣的函數,
這個函數做什麼用呢? 簡單的說就是當你啟動 syslogd 時,
如果呼叫它, 你帶的 message 就會傳給 syslogd,
然後 syslogd 就會幫你紀錄到 /var/log/message 中,

其中的 priority 就是我們剛剛在討論的 level (0-7),
所以...是不是很好改了, 我只要加上:

if (priority < KERN_WARNING) // KERN_WARNING = 4
{
   syslog(priority, "%s", message);
}

就可以讓 klogd 只把 level < 4 的訊息丟給 syslogd,
就這麼簡單.....Open Source 萬歲!


關於 syslog() 函數的使用可以參考這篇:
參考: http://fanqiang.chinaunix.net/a4/b8/20010524/190000219_b.html

ps: 另外, 我第一次 po 文章時所說的 remote log 無法傳送的問題,
    後來發現其實可以正常運作, 可能是我的程式之前沒寫好,
    使用 busybox 的 syslogd 作 remote log的方式是:
    syslogd -R <ipaddr>
    我也測試過 printk() 的訊息可以正確的丟到remote 端.
find /my_brain type sleepy -exec rm -rf {} \;

netman

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 17465
    • 檢視個人資料
    • http://www.study-area.org
不錯不錯!
我早說過: 上完課能夠看得懂你所找到的文章, 那課就沒白上了!
加油加油~~~

wuposheng

  • 憂鬱的高中生
  • ***
  • 文章數: 172
    • 檢視個人資料
那klogd -c 4是不是跟上面的那一段code一樣的作用呢??
就是把kernel log level 4以下的log傳到syslog再傳送到/var/log/messages
還是說這一段command是其他的作用