開發環境
客戶端
開發板:FireFly-RK3399
Linux 4.4
IP:192.168.137.110
服務端
VMware Workstation Pro16,ubuntu 18.04
IP:192.168.137.100
MAC:00:0c:29:c1:9c:ed
netconsole簡介
netconsole模塊可以讓printk信息(輸出到控制臺的信息)通過網絡(UDP)發送到遠程主機。
與串口控制臺不同,netconsole不需要串口線和串口。另外,它可以輕易地將多臺服務器的內核信息收集到一臺服務器上。
當設備上串口無法使用時,使用netconsole將日志信息保存到遠程主機更方便、可行。
netconsole模塊不能用于獲取crash dump,也不能進行一般的控制臺輸入輸出。
netconsole模塊不能獲得網絡相關的kernel panic,以及與操作系統啟動到網絡和netconsole模塊啟動之間發生的pnic相關的內核信息。
netconsole編譯
netconsole 可以獨立編譯為模塊手動加載,也可以編譯進內核自動加載,本例使用的是第一種。
編譯為獨立模塊
netconsole默認是沒有編譯進內核,需要手動編譯到內核或編譯成模塊。
在內核目錄下執行make menuconfig 開啟以下選項
Device Drivers > Network device support>Network console logging support
將內核重新編譯后燒寫到開發板上。
手動編譯netconsole模塊
make CONFIG_NETCONSOLE=m -C /home/zhongyi/code/rk3399_linux_release_v2.5.1_20210301/kernel M=/home/zhongyi/code/rk3399_linux_release_v2.5.1_20210301/kernel/drivers/net modules CROSS_COMPILE=/home/zhongyi/code/rk3399_linux_release_v2.5.1_20210301/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
之后,就會在模塊目錄下生成netconsole.ko的文件,這個文件就是我們所需的。
將netconsole編譯進內核
如自定義內核啟用netconsole只需將以下內核選項打開即可(編譯為模塊).
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
如果將netconsole編譯進內核自動加載,則需要在內核啟動參數中傳遞進去,并且還要確保網卡驅動在netconsole驅動前加載。
netconsole加載
將netconsole.ko通過共享目錄發送到開發板,給予權限,這個需要預先知道服務端的IP地址以及MAC地址。
日志服務器在同一內網, 直接通過ping獲取服務器目的MAC:
$ ping -c 1 192.168.1.103 > /dev/null
$ arp -n 192.168.1.103
Address HWtype HWaddress Flags Mask Iface
192.168.1.103 ether 08:00:46:d4:1d:82 C eth0
1234
日志服務器不在同一內網, 獲取網關目的MAC:
$ netstat -rn | grep ^0.0.0.0
0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 eth0
$ ping -c 1 192.168.1.1 > /dev/null
$ arp -n 192.168.1.1
Address HWtype HWaddress Flags Mask Iface
192.168.1.1 ether 00:0f:66:5b:2a:3c C
執行加載指令
insmod netconsole.ko netconsole=6665@192.168.137.110/eth0,514@192.168.137.100/00:0c:29:c1:9c:ed
各個參數含義如下
netconsole=src-port]@[src-ip]/[],[tgt-port]@/[tgt-macaddr]
where src-port source for UDP packets (defaults to 6665) #開發板上的端口,省略的話默認為6665
src-ip source IP to use (interface address) # 開發板上的IP地址
dev network interface (eth0) #開發板上使用的網卡設備名
tgt-port port for logging agent (6666) #目的機器的端口,省略的話默認為6666
tgt-ip IP address for logging agent #目的機器的IP地址
tgt-macaddr ethernet MAC address for logging agent (broadcast) #目的機器的MAC地址
rsyslog服務端設置
開啟514端口
客戶端設置好了,配置rsyslog以在服務器模式下運行
sudo vim /etc/rsyslog.conf
取消注釋udp和tcp端口綁定的行:
# provides UDP syslog reception
module(load="imudp")
input(type="imudp" port="514")
# provides TCP syslog reception
module(load="imtcp")
input(type="imtcp" port="514")
測試端口是否能通
? ~ sudo nc -vuz 192.168.137.110 514
Connection to 192.168.137.110 514 port [udp/syslog] succeeded!
創建接收模板
創建一個模板,指示rsyslog服務器如何存儲傳入的syslog消息,在GLOBAL DIRECTIVES
部分之前添加模板:
$template remote-incoming-logs,"/var/log/%HOSTNAME%/%fromhost-ip%-%$YEAR%-%$MONTH%-%$DAY%.log
*.* ?remote-incoming-logs
& ~
收到的日志將使用上面的模板進行解析并存儲在目錄/var/log/中,文件命名遵循約定:%HOSTNAME%/%fromhost-ip%-%$YEAR%-%$MONTH%-%$DAY%.log
。
日志接收模板參數的含義可參考:https://www.dandelioncloud.cn/article/details/1517852831246839810
完成后保存并關閉文件。然后,使用以下命令檢查Rsyslog配置是否存在語法錯誤:
rsyslogd -f /etc/rsyslog.conf -N1
你應該看到以下輸出:
rsyslogd: version 8.32.0, config validation run (level 1), master config /etc/rsyslog.conf
rsyslogd: End of config validation run. Bye.
配置啟動文件
以root身份修改/etc/default/rsyslog
啟動配置文件
RSYSLOGD_OPTIONS="-m 0 -r"
- -r 選項以允許接受外來日志消息。
- -x 禁用掉dns記錄項不夠齊全或其他的日志中心的日志。
- -m 修改syslog的內部mark消息寫入間隔時間(0為關閉)。例如-m 180,表示每隔180分鐘(每天8次)在日志文件里增加一行時間戳消息。
- -h 默認情況下,syslog不會發送從遠端接受過來的消息到其他主機,而使用該選項,則把該開關打開,所有接受到的信息都可根據syslog.conf中定義的@主機轉發過去。
重啟服務
重新啟動rsyslog服務以使更改生效:
sudo systemctl restart rsyslog
確認服務是否正在偵聽已配置的端口:
ss -tunelp | grep 514
udp UNCONN 0 0 0.0.0.0:514 0.0.0.0:* ino:178435 sk:2c <->
udp UNCONN 0 0 [::]:514 [::]:* ino:178436 sk:2d v6only:1 <->
tcp LISTEN 0 25 0.0.0.0:514 0.0.0.0:* ino:178439 sk:2e <->
tcp LISTEN 0 25 [::]:514 [::]:* ino:178440 sk:2f v6only:1 <->
配置Rsyslog防火墻
如果你的ufw防火墻服務正在運行,請允許rsyslog防火墻端口:
sudo ufw allow 514/tcp
sudo ufw allow 514/udp
輸出測試
測試使用的是SysRq鍵在客戶端輸出內核信息。
在開發板上,修改/etc/sysctl.conf
啟動SysRq。
kernel.sysrq=1
執行下列命令,使修改生效。
sysctl -p
執行下列命令向控制臺輸出內核信息。
root@firefly:~/mnt/module# echo h > /proc/sysrq-trigger
[10224.626165] sysrq: SysRq : HELP : loglevel(0-9) reboot(b) crash(c) terminate-all-tasks(e) memory-full-oom-kill(f) kill-all-tasks(i) thaw-filesystems(j) sak(k) show-backtrace-all-active-cpus(l) show-memory-usage(m) nice-all-RT-tasks(n) poweroff(o) show-registers(p) show-all-timers(q) unraw(r) sync(s) show-task-states(t) unmount(u) force-fb(V) show-blocked-tasks(w) dump-ftrace-buffer(z)
在服務器的/var/log/192.168.137.110目錄下即可看到生成的日志文件。
? 192.168.137.110 cat 192.168.137.110-2022-10-16.log
2022-10-16T22:35:54.777180+08:00 192.168.137.110 [10224.626165] sysrq: SysRq :
2022-10-16T22:35:54.777180+08:00 192.168.137.110 loglevel(0-9)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 [10224.626165] sysrq: SysRq :
2022-10-16T22:35:54.777180+08:00 192.168.137.110 loglevel(0-9)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 reboot(b)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 crash(c)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 reboot(b)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 crash(c)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 terminate-all-tasks(e)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 terminate-all-tasks(e)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 memory-full-oom-kill(f)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 memory-full-oom-kill(f)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 kill-all-tasks(i)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 kill-all-tasks(i)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 thaw-filesystems(j)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 thaw-filesystems(j)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 sak(k)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 sak(k)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 show-backtrace-all-active-cpus(l)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 show-backtrace-all-active-cpus(l)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 show-memory-usage(m)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 show-memory-usage(m)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 nice-all-RT-tasks(n)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 nice-all-RT-tasks(n)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 poweroff(o)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 poweroff(o)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 show-registers(p)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 show-registers(p)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 show-all-timers(q)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 show-all-timers(q)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 unraw(r)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 unraw(r)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 sync(s)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 sync(s)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 show-task-states(t)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 show-task-states(t)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 unmount(u)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 unmount(u)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 force-fb(V)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 force-fb(V)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 show-blocked-tasks(w)
2022-10-16T22:35:54.777180+08:00 192.168.137.110 show-blocked-tasks(w)
2022-10-16T22:35:54.900989+08:00 192.168.137.110 dump-ftrace-buffer(z)
2022-10-16T22:35:54.900989+08:00 192.168.137.110 dump-ftrace-buffer(z)
2022-10-16T22:35:54.900989+08:00 192.168.137.110
若進入192.168.137.110目錄無權限,則執行 sudo chmod 777 192.168.137.110
賦予權限。
其他監聽方法
netcat
在沒有syslogd在運行的主機上可以使用 netcat/socat 接收來自遠程主機的消息:
nc -u -l -p <port> / nc -u -l <port>
netcat -u -l -p <port> / netcat -u -l <port>
socat udp-recv:<port> -
舉例
~ sudo netcat -l -p 514 -u
[sudo] password for zhongyi:
[ 263.748032] sysrq: SysRq : HELP : [ 263.748032] sysrq: SysRq : HELP : loglevel(0-9) loglevel(0-9) reboot(b) reboot(b) crash(c) crash(c) terminate-all-tasks(e) terminate-all-tasks(e) memory-full-oom-kill(f) memory-full-oom-kill(f) kill-all-tasks(i) kill-all-tasks(i) thaw-filesystems(j) thaw-filesystems(j) sak(k) sak(k) show-backtrace-all-active-cpus(l) show-backtrace-all-active-cpus(l) show-memory-usage(m) show-memory-usage(m) nice-all-RT-tasks(n) nice-all-RT-tasks(n) poweroff(o) show-registers(p) poweroff(o) show-registers(p) show-all-timers(q) show-all-timers(q) unraw(r) sync(s) show-task-states(t) unraw(r) sync(s) show-task-states(t) unmount(u) force-fb(V) unmount(u) force-fb(V) show-blocked-tasks(w) show-blocked-tasks(w) dump-ftrace-buffer(z) dump-ftrace-buffer(z)
dmesg
-n/--console-level
控制kernel message console 輸出級別, 設置輸出level為debug
(-n 8
):
dmesg -n 8
uboot中的netconsole
uboot下的netconsole類似于kernel下的telnet等網絡終端功能,將網絡作為輸入輸出的終端,這樣就便于我們在PC端通過網絡登錄設備uboot中運行命令。
uboot下netconsole的實現在drivers/net/netconsole.c中,uboot開啟netconsole只需要在配置文件configs/firefly-rk3399_defconfig
加入CONFIG_NETCONSOLE=y
即可。重新編譯uboot,燒寫到設備上。
設置環境變量nc
,設置CONFIG_NETCONSOLE_BUFFER_SIZE
覆蓋默認緩沖區大小,設置環境變量ncip
為通信對端ip,格式為
,
不設置時為默認值6666
,發送端口和接收端口可以分別設置,ncinport
和ncoutport
,
setenv ipaddr 192.168.137.110
setenv nc 'setenv stdout nc;setenv stdin nc'
setenv ncip 192.168.137.100
saveenv
run nc
uboot進入netonsole模式,此時串口控制臺就沒有輸出了。
在服務器上執行
./tools/netconsole 192.168.137.110
就可以在PC端運行uboot命令了。
對啦,最近重溫操作系統時發現了一個免費精品好課,閃客的《Linux0.11源碼趣讀》,剛上線第二季了,這個課給我感覺像在用看小說的心態學操作系統源碼,寫的確實挺牛的,通俗易懂,直指本源,我自己也跟著收獲了很多。
發布評論請先 登錄
相關推薦
評論