GuestOS 中如果发生了一些错误,GuestOS 还活着,shel 已经 hung 住了,如何获取到 GuestOS 中的关键 log 信息呢?
QEMU默认虚拟化出来的键盘i8042,它的irq是1,具有非常高的优先级。可见,在大部分情况下,kernel不挂的情况下,都是可以响应键盘中断的。
linux提供了一组magic key,用来触发特定的内核行为。在Linux的文档中,linux-4.4/Documentation/sysrq.txt
有比较具体的描述,在这里截取几个关键的地方:
echo "number" >/proc/sys/kernel/sysrq
,用来打开/关闭sysrq功能。简单一点,number取1就好。
配置好了sysrq之后,键盘中敲alt+prtsc+h
或者在shell中敲echo h > /proc/sysrq-trigger
,再dmesg就可以看到一些帮助信息。
基于上述sysrq,那么可以给GuestOS发送magic key来触发GuestOS的sysrq。但是,如果HostOS也是Linux,那么就会magic会被HostOS截获。不能发送到Guest中。
所以可以使用virsh提供的sendkey能力:
virsh send-key e8adebc4-47f8-4d99-95a4-053ac6c6fb11 KEY_LEFTALT KEY_SYSRQ KEY_T
上面的几个KEY_XXX,作者也记不住,每次都要去libvirt/src/util/virkeymaps.h
中查看。
我们希望把GuestOS的kmsg重定向到Host中的某个文件中,一来方便阅读查看,二来Guest中shell真的hung住了,我们也看不了。
所以,在启动Guest虚拟机之前需要给Guest配置serial设备,在libvirt的文档中使用这样的配置:
<serial type='file'>
<source path='/mnt/console/e8adebc4-47f8-4d99-95a4-053ac6c6fb11.log' append='off'/>
<target port='0'/>
</serial>
在4部配置完成后,启动Guest就可以使用ttyS0设备了。在guest中执行
echo “Hello World” > /dev/ttyS0
,就可以在Host的文件中出现这样的log了。
修改grub的配置,编辑/boot/grub/grub.cfg,修改linux的启动参数:
linux /boot/vmlinuz-4.4.0-21-generic root=UUID=807ac0e5-56ce-4906-8474-3d1f8c5894c4 ro console=ttyS0,115200n8
执行sync,再重启,就可以看到很多log写到了对应的文件中了。
上述的步骤配置完成后,可以看到大量的kernel的log,但是依然不能看到sysrq的log。因为log level的关系。
在GuestOS中,敲cat /proc/sys/kernel/printk
可以看到printk的log level。默认情况下,应该可以看到“4 4 1 7”这样的显示。
printk的log level在linux-4.4/kernel/printk/printk.c中实现,
我们只要关注第一个就行了,在shell中敲echo “8 4 1 7” > /proc/sys/kernel/printk
来调整一下。
接下来再触发sysrq就可以看到log了。
作者这里为了复现一个问题,构造场景的时候,看到了类似的log。在执行write的时候,进程进入了D状态了。也是符合预期的,因为作者是为了测试在GuestOS中写数据的时候,做磁盘热拔的。
sysrq中的c是crash,构造一次crash也挺有趣的,还有就是测试kernel的crash dump功能的时候很有用。
那么,crash是如何实现的呢?
inux-4.4.0/drivers/tty/sysrq.c中,
打开panic on oops,在对空指针赋值,就crash了。其他handler也在这个文件中实现的,略有意思。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。