Netconsole

由 Ingo Molnar <mingo@redhat.com> 啟動, 2001.09.17

Matt Mackall <mpm@selenic.com> 的 2.6 移植和 netpoll api, Sep 9 2003

Cong Wang <xiyou.wangcong@gmail.com> 的 IPv6 支援, Jan 1 2013

Tejun Heo <tj@kernel.org> 的擴充套件控制檯支援, May 1 2015

Breno Leitao <leitao@debian.org> 的釋出字首支援, Jul 7 2023

Matthew Wood <thepacketgeek@gmail.com> 的使用者資料附加支援, Jan 22 2024

Breno Leitao <leitao@debian.org> 的系統資料附加支援, Jan 15 2025

請將錯誤報告發送給 Matt Mackall <mpm@selenic.com> Satyam Sharma <satyam.sharma@gmail.com>, 和 Cong Wang <xiyou.wangcong@gmail.com>

簡介:

此模組透過 UDP 記錄核心 printk 訊息,從而允許除錯磁碟日誌記錄失敗且序列控制檯不切實際的問題。

它可以內建或作為模組使用。作為內建模組,netconsole 會在 NIC 卡之後立即初始化,並將儘快啟動指定的介面。雖然這不允許捕獲早期核心崩潰,但它確實捕獲了大部分啟動過程。

傳送方和接收方配置:

它採用字串配置引數 “netconsole”,格式如下

netconsole=[+][r][src-port]@[src-ip]/[<dev>],[tgt-port]@<tgt-ip>/[tgt-macaddr]

  where
       +             if present, enable extended console support
       r             if present, prepend kernel version (release) to the message
       src-port      source for UDP packets (defaults to 6665)
       src-ip        source IP to use (interface address)
       dev           network interface name (eth0) or MAC address
       tgt-port      port for logging agent (6666)
       tgt-ip        IP address for logging agent
       tgt-macaddr   ethernet MAC address for logging agent (broadcast)

示例

linux netconsole=4444@10.0.0.1/eth1,9353@10.0.0.2/12:34:56:78:9a:bc

insmod netconsole netconsole=@/,@10.0.0.2/

或使用 IPv6

insmod netconsole netconsole=@/,@fd00:1:2:3::1/

或使用 MAC 地址選擇出口介面

linux netconsole=4444@10.0.0.1/22:33:44:55:66:77,9353@10.0.0.2/12:34:56:78:9a:bc

它還支援透過指定用分號分隔的多個代理的引數並將完整的字串括在“引號”中來記錄到多個遠端代理,如下所示

modprobe netconsole netconsole="@/,@10.0.0.2/;@/eth1,6892@10.0.0.3/"

內建 netconsole 在 TCP 堆疊初始化後立即啟動,並嘗試以提供的地址啟動提供的裝置。

遠端主機有幾個選項可以接收核心訊息,例如

  1. syslogd

  2. netcat

    在使用基於 BSD 的 netcat 版本的發行版(例如 Fedora、openSUSE 和 Ubuntu)上,必須在不使用 -p 開關的情況下指定偵聽埠

        nc -u -l -p <port>' / 'nc -u -l <port>
    
    or::
    
        netcat -u -l -p <port>' / 'netcat -u -l <port>
    
  3. socat

socat udp-recv:<port> -

動態重新配置:

動態可重新配置性是 netconsole 的一個有用補充,它允許從基於 configfs 的使用者空間介面動態新增、刪除遠端日誌記錄目標或重新配置其引數。

要包含此功能,請在構建 netconsole 模組(或核心,如果 netconsole 是內建的)時選擇 CONFIG_NETCONSOLE_DYNAMIC。

以下是一些示例(其中 configfs 安裝在 /sys/kernel/config 掛載點)。

要新增遠端日誌記錄目標(目標名稱可以是任意的)

cd /sys/kernel/config/netconsole/
mkdir target1

請注意,新建立的目標具有預設引數值(如上所述)並且預設情況下已停用 -- 必須首先透過將 “1” 寫入 “enabled” 屬性來啟用它們(通常是在相應地設定引數之後),如下所述。

要刪除目標

rmdir /sys/kernel/config/netconsole/othertarget/

該介面向用戶空間公開 netconsole 目標的這些引數

enabled

當前是否啟用了此目標?

(讀寫)

extended

啟用擴充套件模式

(讀寫)

release

將核心版本新增到訊息前

(讀寫)

dev_name

本地網路介面名稱

(讀寫)

local_port

要使用的源 UDP 埠

(讀寫)

remote_port

遠端代理的 UDP 埠

(讀寫)

local_ip

要使用的源 IP 地址

(讀寫)

remote_ip

遠端代理的 IP 地址

(讀寫)

local_mac

本地介面的 MAC 地址

(只讀)

remote_mac

遠端代理的 MAC 地址

(讀寫)

transmit_errors

資料包傳送錯誤數

(只讀)

“enabled” 屬性還用於控制是否可以更新目標的引數 -- 您只能修改已停用的目標的引數(即,如果 “enabled” 為 0)。

要更新目標的引數

cat enabled                            # check if enabled is 1
echo 0 > enabled                       # disable the target (if required)
echo eth2 > dev_name                   # set local interface
echo 10.0.0.4 > remote_ip              # update some parameter
echo cb:a9:87:65:43:21 > remote_mac    # update more parameters
echo 1 > enabled                       # enable target again

您還可以動態更新本地介面。如果您想使用新出現的介面(並且可能在 netconsole 載入/初始化時不存在),這將特別有用。

在啟動時(或模組載入時)使用 netconsole= 引數定義的 Netconsole 目標會被分配名稱 cmdline<index>。例如,引數中的第一個目標被命名為 cmdline0。您可以透過建立具有匹配名稱的 configfs 目錄來控制和修改這些目標。

假設您在啟動時定義了兩個 netconsole 目標

netconsole=4444@10.0.0.1/eth1,9353@10.0.0.2/12:34:56:78:9a:bc;4444@10.0.0.1/eth1,9353@10.0.0.3/12:34:56:78:9a:bc

您可以透過建立以下目標在執行時修改這些目標

mkdir cmdline0
cat cmdline0/remote_ip
10.0.0.2

mkdir cmdline1
cat cmdline1/remote_ip
10.0.0.3

附加使用者資料

啟用 netconsole 動態配置後,可以將自定義使用者資料附加到訊息末尾。可以修改使用者資料條目,而無需更改目標的 “enabled” 屬性。

userdata 下的目錄(鍵)限制為 53 個字元長度,userdata/<key>/value 中的資料限制為 200 個位元組

cd /sys/kernel/config/netconsole && mkdir cmdline0
cd cmdline0
mkdir userdata/foo
echo bar > userdata/foo/value
mkdir userdata/qux
echo baz > userdata/qux/value

訊息現在將包含此額外的使用者資料

echo "This is a message" > /dev/kmsg

傳送

12,607,22085407756,-;This is a message
 foo=bar
 qux=baz

使用以下命令預覽將附加的使用者資料

cd /sys/kernel/config/netconsole/cmdline0/userdata
for f in `ls userdata`; do echo $f=$(cat userdata/$f/value); done

如果建立了 userdata 條目但沒有資料寫入 value 檔案,則該條目將從 netconsole 訊息中省略

cd /sys/kernel/config/netconsole && mkdir cmdline0
cd cmdline0
mkdir userdata/foo
echo bar > userdata/foo/value
mkdir userdata/qux

qux 鍵被省略,因為它沒有值

echo "This is a message" > /dev/kmsg
12,607,22085407756,-;This is a message
 foo=bar

使用 rmdir 刪除 userdata 條目

rmdir /sys/kernel/config/netconsole/cmdline0/userdata/qux

警告

當將字串寫入使用者資料值時,輸入會按 configfs 儲存呼叫中的每行進行分解,這可能會導致令人困惑的行為

mkdir userdata/testing
printf "val1\nval2" > userdata/testing/value
# userdata store value is called twice, first with "val1\n" then "val2"
# so "val2" is stored, being the last value stored
cat userdata/testing/value
val2

建議不要使用換行符編寫使用者資料值。

使用者資料中的任務名稱自動填充

在 netconsole configfs 層次結構中,userdata 目錄下有一個名為 taskname_enabled 的檔案。此檔案用於啟用或停用自動任務名稱填充功能。此功能會自動填充在傳送訊息的 CPU 中排程的當前任務名稱。

啟用任務名稱自動填充

echo 1 > /sys/kernel/config/netconsole/target1/userdata/taskname_enabled

啟用此選項後,netconsole 訊息將在使用者資料欄位中包含一個額外的行,格式為 taskname=<任務名稱>。這允許 netconsole 訊息的接收者輕鬆找到生成該訊息時當前排程的應用程式,為核心訊息提供額外的上下文並幫助對其進行分類。

示例

echo "This is a message" > /dev/kmsg
12,607,22085407756,-;This is a message
 taskname=echo

在此示例中,該訊息是在 “echo” 是當前排程程序時生成的。

使用者資料中的核心版本自動填充

在 netconsole configfs 層次結構中,有一個名為 release_enabled 的檔案位於 userdata 目錄中。此檔案控制核心版本自動填充功能,該功能將核心版本資訊附加到每個傳送的訊息中的使用者資料字典中。

啟用版本自動填充

echo 1 > /sys/kernel/config/netconsole/target1/userdata/release_enabled

示例

echo "This is a message" > /dev/kmsg
12,607,22085407756,-;This is a message
 release=6.14.0-rc6-01219-g3c027fbd941d

注意

此功能提供與 “release prepend” 功能相同的資料。但是,在這種情況下,版本資訊附加到使用者資料字典中,而不是包含在訊息頭中。

使用者資料中的 CPU 編號自動填充

在 netconsole configfs 層次結構中,userdata 目錄下有一個名為 cpu_nr 的檔案。此檔案用於啟用或停用自動 CPU 編號填充功能。此功能會自動填充發送訊息的 CPU 編號。

啟用 CPU 編號自動填充

echo 1 > /sys/kernel/config/netconsole/target1/userdata/cpu_nr

啟用此選項後,netconsole 訊息將在使用者資料欄位中包含一個額外的行,格式為 cpu=<cpu_number>。這允許 netconsole 訊息的接收者輕鬆區分和解複用來自不同 CPU 的訊息,這在處理並行日誌輸出時特別有用。

示例

echo "This is a message" > /dev/kmsg
12,607,22085407756,-;This is a message
 cpu=42

在此示例中,該訊息由 CPU 42 傳送。

注意

如果使用者在使用者資料字典中設定了衝突的 cpu 鍵,則將報告兩個鍵,其中核心填充的條目出現在使用者條目之後。例如

# User-defined CPU entry
mkdir -p /sys/kernel/config/netconsole/target1/userdata/cpu
echo "1" > /sys/kernel/config/netconsole/target1/userdata/cpu/value

輸出可能如下所示

12,607,22085407756,-;This is a message
 cpu=1
 cpu=42    # kernel-populated value

擴充套件控制檯:

如果在配置行中新增字首 ‘+’ 或將 “extended” 配置檔案設定為 1,則啟用擴充套件控制檯支援。以下是一個啟動引數示例

linux netconsole=+4444@10.0.0.1/eth1,9353@10.0.0.2/12:34:56:78:9a:bc

日誌訊息以擴充套件元資料標頭傳輸,格式如下,與 /dev/kmsg 相同

<level>,<sequnum>,<timestamp>,<contflag>;<message text>

如果啟用了 ‘r’(釋出)功能,則核心版本會新增到訊息的開頭。例如

6.4.0,6,444,501151268,-;netconsole: network logging started

<message text> 中的不可列印字元使用 “xff” 表示法進行轉義。如果訊息包含可選字典,則逐字換行符用作分隔符。

如果訊息不適合一定數量的位元組(目前為 1000),則訊息會被 netconsole 分割成多個片段。這些片段以新增的 “ncfrag” 標頭欄位傳輸

ncfrag=<byte-offset>/<total-bytes>

例如,假設塊大小小得多,訊息 “the first chunk, the 2nd chunk.” 可能會拆分如下

6,416,1758426,-,ncfrag=0/31;the first chunk,
6,416,1758426,-,ncfrag=16/31; the 2nd chunk.

其他說明:

警告

預設目標乙太網設定使用廣播乙太網地址傳送資料包,這可能會導致同一乙太網段上其他系統的負載增加。

提示

某些 LAN 交換機可能配置為抑制乙太網廣播,因此建議從傳遞給 netconsole 的配置引數中顯式指定遠端代理的 MAC 地址。

提示

要找出例如 10.0.0.2 的 MAC 地址,您可以嘗試使用

ping -c 1 10.0.0.2 ; /sbin/arp -n | grep 10.0.0.2

提示

如果遠端日誌記錄代理與傳送方位於不同的 LAN 子網上,則建議嘗試指定預設閘道器的 MAC 地址(您可以使用 /sbin/route -n 找到它)作為遠端 MAC 地址。

注意

網路裝置(在上述情況下為 eth1)可以執行任何其他型別的網路流量,netconsole 不會造成干擾。如果核心訊息量很大,Netconsole 可能會導致其他流量略有延遲,但應該沒有其他影響。

注意

如果您發現遠端日誌記錄代理沒有收到或列印來自發送方的所有訊息,則可能是您已將 “console_loglevel” 引數(在傳送方上)設定為僅將高優先順序訊息傳送到控制檯。您可以使用以下命令在執行時更改此設定

dmesg -n 8

或者透過在啟動時在核心命令列上指定 “debug”,將所有核心訊息傳送到控制檯。還可以使用 “loglevel” 核心引導選項設定此引數的特定值。有關詳細資訊,請參閱 dmesg(8) 手冊頁和 核心的命令列引數

Netconsole 的設計目標是儘可能快,以便能夠記錄最關鍵的核心錯誤。它也可以從 IRQ 上下文中工作,並且在傳送資料包時不會啟用中斷。由於這些獨特的需要,配置不可能更自動,並且一些基本限制將保留:僅支援 IP 網路、UDP 資料包和乙太網裝置。