手動添加kdump


背景:
     Linux嵌入式設備內核掛死后,無法自動重啟,需要手動重啟。而且如果當時沒有連串口的話,就無法記錄內核掛死時的堆棧,所以需要添加一種方式來記錄內核掛死信息方便以后調試使用。設備中增加kdump功能,可以將內核掛死的堆棧信息記錄下來,供后期分析。

操作步驟:
        1、添加kdump所需的程序及配置文件
        方法:目前所分析得知需要如下文件/sbin/kdump /sbin/kexec /bin/kdumpctl /etc/kdump.conf /etc/sysconfig/kdump,然后編輯etc目錄下的兩個配置文件;修改kdump中KDUMP_BOOTDIR="/mnt",KDUMP_COMMANDLINE_APPEND="1 irqpoll maxcpus=1",KDUMP_IMG="kernel.img";修改kdump.conf內容為path /mnt/workdir/log;還需要修改kdumpctl中有關kdump和kexec的路徑;將這些文件放到設備的mnt目錄下然后重啟,重啟后執行kexec -l /mnt/kernel.img --initrd=/mnt/rootfs.img --command-line="`cat /proc/cmdline`  1 irqpoll maxcpus=1";kexec -e 查看是否添加成功。
        
        2、問題:各種工具、配置文件均添加成功,但是執行kdumpctl start命令時,依然報錯 BUG: unable to handle kernel paging request at ffff880001497000,或者不打印堆棧信息直接提示killed。
        解決方法:經過測試,將添加到grub.cfg中的crashkernel=128M@16M改成crashkernel=128M,完全省略“@Y”這一部分,這樣,kernel 會為我們自動選擇一個起始地址。這樣就不會出現起始地址錯誤等問題了。在測試kexec時,最好加上-d選項,將debug信息打印出來。

        3、問題:經測試,按照第二步中的操作方法,kexec -e執行完成后,內核打完堆棧之后並未重啟,而是直接卡死了。
        解決方法:分析之后才發現,因為在/etc/sysconfig/kdump配置文件KDUMP_COMMANDLINE_APPEND字段添加了reset_devices,所以導致kdump內核無法重啟。將KDUMP_COMMANDLINE_APPEND選項內容中reset_devices這個值刪掉就可以了。
        
        4、問題:內核panic錯誤發生后,內核重啟,但是只進入到了新解壓后的rootfs中,而系統的inittab根本就未被執行,導致后續的腳本沒有執行。
        解決方法:經過查找相關資料發現,linux在內核加載完成后,會解壓initrd成rootfs根文件系統,隨后執行根文件系統中的linuxrc或者init來初始化inittab配置文件,然后進行一系列的腳本初始化操作。根據現象發現,inittab確實沒有被執行過,所以就開始查找inittab未被執行的原因。然后修改/etc/sysconfig/kdump文件中的KDUMP_COMMANDLINE_APPEND的值為"1 irqpoll maxcpus=1 init=/linuxrc",然后就可以執行成功了。

        5、問題:由於采用原有的rootfs會造成設備啟動許多不必要的程序、服務,所以應該重新定制一個kdump專用的rootfs。
        解決方法:下載新版的busybox,然后編譯、安裝生成_install目錄,該目錄下就是部分文件系統,然后在創建dev,etc,lib,lib64,var,proc,tmp,mnt,sys這些系統所需的目錄以及設備所需的workdir,mnt目錄。由於編譯busybox時,采用靜態編譯出錯,所以沒有采用靜態編譯的方式,因而需要用ldd busybox查看busybox所需的動態庫,然后將這些動態庫拷貝到創建好的/lib64目錄中。由於linuxrc需要初始化系統,因而需要在/etc目錄下添加fstab、inittab以及init.d/rcS這三個必備文件,由於fstab和inittab只跟系統有關,所以可以借用原來rootfs的對應文件,rcS系統程序的初始化腳本,可以將自己所需要實現的命令添加到rcS中,還需要在dev目錄中添加相關設備節點,用mknod命令添加console, null等設備以及shm,pts目錄作為掛載點。由於kdump重啟后的系統中生成的vmcore過大,CF卡存儲不下,只能用vmcore-dmesg /proc/vmcore命令提取內核崩潰日志,所以rcS就簡單實現了掛載文件系統、CF卡、提取內核崩潰信息,然后重啟系統的功能。由於新的rootfs是在kdump過程中使用,與原有的rootfs獨立,所以提取內核崩潰日志的相關程序就需要預先添加到新的rootfs相關的目錄中。整個rootfs目錄文件添加完成之后,就在_install目錄下執行find . | cpio -H newc --quiet -o | gzip -9 >~/rootfs.img,將這些文件夾打包並壓縮生成rootfs.img放到當前用戶的home目錄。

        6、問題:kdumpctl啟動kdump服務時,要求內核以及initrd的名稱格式,而且需要修改boot.cfg啟動配置文件。
        解決方案:最開始向采用修改安裝包的方式,向安裝包中添加kdump需要的內核以及initrd文件,但是經過嘗試無法將這些文件打到vsos.bin中,后來發現是package.ini文件的配置,修改package.ini的配置后,可以將對應的文件添加到vsos.bin中了。但是在設備安裝的時候,依然沒有安裝新添加的文件。由於對設備解包安裝的過程不太熟悉,所以就采取折衷的方式:將新的initrd(即kdump需要的rootfs文件)添加到/mnt/system目錄下,然后在開機啟動腳本start.sh中,添加修改boot.cfg的功能,並將新的rootfs文件移至/mnt目錄下,同時新建一個對原有內核文件的軟連接供kdump使用,由於kdumpctl會檢查內核文件、initrd文件、以及kdump的配置文件的時間戳,如果initrd文件的時間戳早於其他文件,kdumpctl嘗試重新生成initrd文件,這個過程中很有可能報錯,所以在移動文件結束后,就會用touch命令更新initrd文件的時間到最新。

        7、問題:CF卡的磁盤編號有時不是/dev/sda1,導致kdump重啟后按照/dev/sda1掛載失敗
        解決方法:用這個命令fdisk -l | grep "83" | grep "\*" | grep dev | awk '{print $1}'來獲取CF卡的設備號。

內容匯總
kexec -l選項是直接加載內核,然后配置kexec -e命令啟動新內核;而kexec -p選項則是指明當前內核遇到panic時,要啟用的內核。需要echo c>/proc/sysrq-trigger,手動觸發內核panic。
其實完全可以用kexec取代kdumpctl,這樣就可以直接用老的內核名稱,而且也不用考慮對kernel、initrd及配置文件的時間戳問題,而且由於采用的是新的rootfs系統,通過修改rcS腳本自己手動實現的內核崩潰信息保存,完全可以脫離對kdump相關配置文件的依賴,這樣做是最簡單的。但是考慮到標准linux中啟動kdump的方式兼容,方便后續人員維護,就采用了kdumpctl的方式啟動kdump服務。
由於在svn上提交的是一個封裝好的img文件,所以要想對修改img文件中的內容,則需要先將img文件拷貝到一個新的文件夾下,然后執行:mv rootfs.img rootfs.img.gz; gzip -d rootfs.img.gz; cpio -id 還原出整個文件系統,然后按照需求進行修改,隨后執行find . | cpio -H newc --quiet -o | gzip -9 >~/rootfs.img重新生成img文件。上述重新生成img文件的命令中,最后img文件的位置不能在當前目錄。
得失分析:
由於對內核相關內容不太熟悉,所以前期只能通過從網上找相關資料,一點點嘗試。雖然這個過程難了點兒,但是自己從中還是學到了很多東西,諸如Linux啟動過程的詳細過程之類的,學會了裁剪內核以及busybox,可以搭建一個小的迷你linux。
由於時間限制,並未進一步實現提取vmcore的功能。不過在現在有工作的基礎之上應該很容易添加獲取vmcore的功能。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM