Netconsole

由 Ingo Molnar <mingo@redhat.com> 于 2001.09.17 启动

Matt Mackall <mpm@selenic.com> 于 2003 年 9 月 9 日移植到 2.6 版本并使用 netpoll api

Cong Wang <xiyou.wangcong@gmail.com> 于 2013 年 1 月 1 日支持 IPv6

Tejun Heo <tj@kernel.org> 于 2015 年 5 月 1 日扩展控制台支持

Breno Leitao <leitao@debian.org> 于 2023 年 7 月 7 日支持发布版本前缀

Matthew Wood <thepacketgeek@gmail.com> 于 2024 年 1 月 22 日支持附加用户数据

请将错误报告发送给 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 (eth0)
       tgt-port      port for logging agent (6666)
       tgt-ip        IP address for logging agent
       tgt-macaddr   ethernet MAC address for logging agent (broadcast)

示例

linux [email protected]/eth1,[email protected]/12:34:56:78:9a:bc

insmod netconsole netconsole=@/,@10.0.0.2/

或使用 IPv6

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

它还支持通过使用分号分隔的多个代理的参数并将完整的字符串括在“引号”中来记录到多个远程代理,如下所示

modprobe netconsole netconsole="@/,@10.0.0.2/;@/eth1,[email protected]/"

内置 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 地址

(读写)

“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 目标

[email protected]/eth1,[email protected]/12:34:56:78:9a:bc;[email protected]/eth1,[email protected]/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

建议不要使用换行符写入用户数据值。

扩展控制台:

如果配置行前缀为“+”或“extended”配置文件设置为 1,则启用扩展控制台支持。下面是一个引导参数示例

linux [email protected]/eth1,[email protected]/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

<消息文本> 中的不可打印字符使用“xff”表示法进行转义。如果消息包含可选字典,则使用原义换行符作为分隔符。

如果消息不适合特定数量的字节(当前为 1000),则该消息将由 netconsole 分成多个片段。这些片段使用添加的“ncfrag”标头字段进行传输

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

例如,假设一个小的多的块大小,消息“第一个块,第二个块。” 可以按如下方式拆分

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 数据包和以太网设备。