Вопрос или проблема
Команда
Вот что я делаю
# Шаг 1. На хост-машине
$ qemu-system-x86_64 \
-enable-kvm -nodefaults -nographic -L /usr/share/qemu \
-m 8G -smp 4 -boot c \
-netdev user,hostnet0,hostfwd=tcp::5556-:22 \
-drive file=ubuntu18.04.qcow2,if=virtio,cache=none \
-device virtio-net-pci,netdev=hostnet0,id=net0,bus=pci.0,addr=0x3\
-serial pty
# Шаг 2. На гостевой машине
$ sudo vim /etc/default/grub
# Измените GRUB_CMDLINE_LINUX="" на GRUB_CMDLINE_LINUX="console=ttyS0"
# Шаг 3. На хост-машине
# Должен быть напечатан лог, показывающий
# какой pty используется, когда хост запускает qemu
# Пусть будет, /dev/pts/3
$ sudo cat /dev/pts/3
# Шаг 4. Вход в /dev/pts/3
$ echo "id" > /dev/pts/3
$ echo "password" > /dev/pts/3
# Шаг 5. Вывести dmesg в лог-файл
$ echo dmesg > /dev/pts/3
Что я хочу, так это получить лог ядра от гостевой машины. Код выше в основном использует pty как последовательный порт, так что я могу получать лог через определенный tty, но проблема в том, что существует предупреждение для этого метода.
Если я выполню команду, dmesg
, я получаю это сообщение:
[ 0.00000] serial8250: слишком много работы для irq4
Я не верю, что это критическое предупреждение, но оно довольно раздражает, и мне кажется, что несколько логов игнорируются.
Я хотел бы знать, есть ли лучший способ получить лог без каких-либо предупреждений из виртуальной машины. Я чувствую, что это предупреждение неуместно. Способ, которым я это исправляю, — это регулярно заходить в систему и перенаправлять некрасивый вывод cat
.
Есть ли способ получить лог сразу же без использования echo dmesg?
Альтернатива
# Используя именованный трубопровод
# Шаг 1. конфигурация qemu
$ qemu-system-x86_64 \
-некоторые параметры, как выше \
-serial pipe:/tmp/guest
# Шаг 2. Для получения лога
$ mkfifo /tmp/guest.in /tmp/guest.out
$ cat /tmp/guest.out
$ printf "id\n" > /tmp/guest.in
$ printf "pw\n" > /tmp/guest.in
$ printf "cmd\n" > /tmp/guest.in
Вы можете добавить -serial file:console.log
к qemu-system
и добавить console=ttyS0,115200 ignore_loglevel
к параметрам ядра гостевой системы.
С ignore_loglevel
все сообщения ядра выводятся в консоль (здесь серийное устройство) независимо от их уровня логирования.
Вы можете попробовать этот инструмент kvm-dmesg
$ ./kvm-dmesg /tmp/qmp.sock System.map-5.15.171
[ 0.000000] Версия Linux 5.15.171 (rayylee@ubuntu-dev) (gcc (Ubuntu 13.2.0-23ubuntu4) 13.2.0, GNU ld (GNU Binutils для Ubuntu) 2.42) #1 SMP Вт Ноя 12 14:44:05 UTC 2024
[ 0.000000] Командная строка: console=ttyS0
[ 0.000000] Карта физической оперативной памяти, предоставленная BIOS:
[ 0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] доступно
[ 0.000000] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] зарезервировано
[ 0.000000] BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] зарезервировано
[ 0.000000] BIOS-e820: [mem 0x0000000000100000-0x000000001ffdffff] доступно
[ 0.000000] BIOS-e820: [mem 0x000000001ffe0000-0x000000001fffffff] зарезервировано
Ответ или решение
Как вывести вывод dmesg на хостовую машину из гостевой ВМ QEMU
Виртуализация с использованием QEMU предоставляет разработчикам и системным администраторам мощные инструменты для тестирования и отладки. Одной из задач может быть запись логов ядра из гостевой системы на хостовую машину. В этом ответе мы рассмотрим несколько методов для выполнения этой задачи, а также обсудим предупреждения, возникающие в процессе.
Шаги по настройке и вывод dmesg
-
Настройка QEMU: Для начала мы запустим QEMU с нужными параметрами. Ваша команда уже содержит основные опции для запуска гостевой системы. Добавление параметра для серийного порта позволяет получить доступ к логам в реальном времени.
qemu-system-x86_64 \ -enable-kvm -nodefaults -nographic -L /usr/share/qemu \ -m 8G -smp 4 -boot c \ -netdev user,hostnet0,hostfwd=tcp::5556-:22 \ -drive file=ubuntu18.04.qcow2,if=virtio,cache=none \ -device virtio-net-pci,netdev=hostnet0,id=net0,bus=pci.0,addr=0x3 \ -serial file:/tmp/guest.log
Здесь параметр
-serial file:/tmp/guest.log
будет выводить логи в указанный файл, который вы сможете просматривать на хостовой машине. -
Конфигурация GRUB в гостевой системе: Важно отредактировать конфигурацию GRUB для перенаправления вывода консоли.
sudo vim /etc/default/grub
Измените строку
GRUB_CMDLINE_LINUX=""
наGRUB_CMDLINE_LINUX="console=ttyS0,115200 ignore_loglevel"
. Параметрignore_loglevel
понадобится для того, чтобы все сообщения ядра выводились на консоль, игнорируя уровень важности. После редактирования, обновите конфигурацию GRUB:sudo update-grub
-
Перезапуск гостевой системы: Перезапустите виртуальную машину, чтобы применить изменения конфигурации.
-
Просмотр логов: Теперь вы можете мониторить файл
/tmp/guest.log
на хостовой системе:tail -f /tmp/guest.log
Теперь данные dmesg
можно будет видеть в этом файле, избегая предупреждений, связанных с перегрузкой прерываний.
Альтернативные методы
-
Использование именованных каналов (FIFO): Вы также можете создать именованные каналы для интерактивного взаимодействия.
mkfifo /tmp/guest.in /tmp/guest.out
Затем в одном терминале запускаете:
cat /tmp/guest.out
А в другом – отправляете команды:
printf "id\n" > /tmp/guest.in printf "pw\n" > /tmp/guest.in printf "dmesg\n" > /tmp/guest.in
-
Инструменты сторонних разработчиков: Вы можете рассмотреть использование таких инструментов, как kvm-dmesg, которые позволяют извлекать вывод dmesg через QMP:
./kvm-dmesg /tmp/qmp.sock System.map-5.15.171
Заключение
Настройка вывода логов ядра из гостевой системы QEMU на хост состоит из нескольких шагов, включая правильную конфигурацию параметров запуска и редактирование параметров GRUB. Использование таких методов, как вывод в файл или именованные каналы, позволяет избежать проблемы с предупреждениями и получить более чистый вывод логов. Экспериментируйте с предложенными методами, чтобы выбрать наиболее подходящее решение для ваших задач виртуализации.