null

Полезная магия VirtualBox

В ходе эксплуатации этой замечательной среды виртуализации для ковыряния во внутренностях операционных систем, выяснилось, что внутри VirtualBox сокрыто множество полезностей для этого. Спешу ими поделиться.
Замечу, что сказанное в основном рекомендации касаются Unix-подобных операционных систем.

Несколько шорткатов VBoxManage

Для начала несколько полезных команд, которые лень запоминать.

Посмотреть список всех зарегестрированных и запущенных в данный момент виртуалок можно так:
# VBoxManage list vms
# VBoxManage list runningvms


Конфигурацию виртуальной машины показывает подкоманда showvminfo:
# VBoxManage showvminfo <VM-name>

Запустить виртуальную машину можно с помощью команды VBoxHeadless - при этом не создается отдельного окна, соответственно ее можно запустить в ssh-сессии сидя через GPRS-модем:
# nohup VBoxHeadless -s <VM-name> &

Чтобы получить доступ к консоли виртуальной машины потребуется пакет Extension Pack, настроить порт VRDP, после чего можно будет подключиться обычный rdesktop:
# VBoxManage modifyvm <VM-name> --vrde on --vrdeport <Номер порта>

Включить/отключить линк на 1-м сетевом интерфейсе можно например так:
# VBoxManage controlvm setlinkstate1 on|off

Чтобы подключить ISO-диск, сначала нужно выяснить полный путь до порта, к которому он будет подключен в выводе подкоманды showvminfo:
IDE контроллер (1, 0): /home/myaut/shared/ISO/linux/CentOS-5.6-x86_64-LiveCD.iso

Если соответствующего контролера нет, его можно создать через подкоманду storagectl. Подключим другой ISO-диск к этому порту:
# VBoxManage storageattach CentOS-MPI1 --storagectl 'IDE контроллер' \
        --port 1 --device 0
--type dvddrive \
        --medium '/home/myaut/shared/ISO/linux/CentOS-5.8-x86_64-bin-DVD-1of2.iso'

 

Посылаем NMI или комбинацию SysRq в виртуальную машину

Когда внутри виртуальной машины что-то зависает, самый быстрый и простой способ - ее перезагрузить. Но для меня такой вариант явно не подходит: например в Solaris попасть в отладчик ядра можно только инициировав немаскируемое прерывание (NMI). В VirtualBox это можно сделать так:
# VBoxManage debugvm <VM-name> injectnmi

Для того, чтобы NMI в Solaris вызывал панику или вход в отладчик ядра, нужно использовать следующие параметры ядра (один из двух), указанные в /etc/system:
set pcplusmp:apic_kmdb_on_nmi=1
set pcplusmp:apic_panic_on_nmi=1


Замечу, что данная опция работает только с контроллером прерываний APIC, к тому же обслуживаемый драйвером pcplusmp. Кроме него есть драйвер apix, соответственно его и нужно указывать в /etc/system перед двоеточием.

В Linux много полезных действий выполняется через комбинацию клавиш Alt-SysRq-<буква>, например клавиша T покажет дамп стека ядра для всех процессов (например это полезно чтобы отловить процессы "повисшие" на NFS), а C - вызовет дамп ядра через Kdump. Подробнее об этих комбинациях расскажет википедия: http://en.wikipedia.org/wiki/Magic_SysRq_key

Беда в том, что если в качестве хоста выступает тоже Linux-система, сломаем мы ее, а не виртуалку. Поэтому посылать SysRq-комбинацию мы будем через интерфейс VBoxManage:
# VBoxManage controlvm <VM-name> keyboardputscancode 1d 38 54 2e d4 b8 9d
# VBoxManage controlvm <VM-name> keyboardputscancode 1d 38 54 ae d4 b8 9d


Здесь в качестве примера дается crashdump ядра (комбинация 2e в середине означает нажатие кнопки C, а ae - ее отжатие).
Подробнее о скан-кодах в Linux можно посмотреть здесь: http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html

Создаем сырой диск

Как правило образы виртуальных машин размещаются на файловой системе в виде файлов *.vdi и тому подобных. А что если мы хотим поместить их на сырой диск или том LVM или ZFS? Для этого нужно создать специальный VMDK-файл и сделать это можно например так:
# VBoxManage internalcommands createrawvmdk -filename raw.vmdk          \
        -rawdisk /dev/zvol/dsk/devpool/dc/illumos-2013/media/volume


Замечу, что в VMDK-файл попадает также и информация о геометрии диска, поэтому при увеличении размера тома, придется пересоздать VMDK-файл. Такой способ также будет полезен и при использовании загрузочных флешек.

Если необходимо превратить сырой диск обратно в файловый образ, это можно сделать с помощью команды convertfromraw:
# VBoxManage convertfromraw /dev/zvol/dsk/devpool/dc/illumos-2013/media/volume \
illumosraw.vdi --format VDI

Работаем с последовательным портом

В отличие от глупой и неудобной Windows, которая без графического интерфейса даже в конфигурации Server Core никак, Unix-way системы можно заставить использовать в качестве основного интерфейса (т.н. системной консоли) - последовательный порт. Это требует конфигурации загрузчика Grub, в частности для GRUB1 эта конфигурация выглядит так:
serial --unit=0 --speed=115200
terminal serial


Со стороны самих операционных систем конфигурация последовательного порта как системной консоли выглядит следующим образом. В Linux нужно указать в коммандной строке ядра следующий параметр:
console=ttyS0,115200n8

Кроме этого, нужно заставить init запустить на этом терминале соответствующие службы - с помощью одной из *getty-команд. Например в Debian 5 это делается раскомментированием следующей строчки в /etc/inittab:
T0:23:respawn:/sbin/getty -L ttyS0 115200 vt100

В Solaris нужно в параметрах ядра указать также параметр console:
-B console=ttya
если параметры, заданные через опцию -B уже присутствуют, то console=ttya нужно добавить через запятую.

А в файле /boot/solaris/bootenv.rc (на файловой системе ZFS соответственно /rpool/boot/solaris/bootenv.rc) указать следующие строчки:
setprop ttya-mode '115200,8,n,1,-'
setprop console 'ttya'
setprop input-device 'ttya'
setprop output-device 'ttya'


Никаких действий с службами производить не нужно, т.к. сервис console-login всегда стартует с терминалом /dev/console, который мы переназначили на ttya

Теперь время сконфигурировать терминал со стороны VirtualBox:
# VBoxManage modifyvm <VM-name> --uart1 0x03f8 4
# VBoxManage modifyvm <VM-name> --uartmode1 server /tmp/linux-serial


В режиме server VirtualBox создает Unix-сокет, который позволяет общаться с ним. Проблема в том, что нельзя просто взять и сказать screen /tmp/linux-serial. Поможет нам в этой проблеме замечательная утилита socat (ссылка: http://www.dest-unreach.org/socat/). Первый вариант ее использования - создавать виртуальные pty-терминалы и соответственно наш любимый :

#!/bin/bash

SOCKET=$1
PTYLINK=$1-pty

[ "$1" ] || { echo "usage: $0 PIPE"; exit 1; }

while [ ! -e $SOCKET ]
do
        echo "Polling for $SOCKET"
        sleep 1
done

if [ ! -e $PTYLINK ]
then
        socat UNIX-CONNECT:$SOCKET PTY,link=$PTYLINK &
fi

screen $PTYLINK



Второй вариант заключается в использовании непосредственно возможностей socat для общения со стандартным вводом-выводом, хотя в этом случае выход из пайпа возможен только после выключения виртуальной машины или kill'а процесса socat.
 

#!/bin/sh

[ "$1" ] || { echo "usage: $0 PIPE"; exit 1; }


while [ ! -e $1 ]
do
        echo "Polling for $1"
        sleep 1
done

trap "stty sane" 0 1 2 3 15
socat unix-connect:$1 stdio,raw,echo=0,icanon=0



Кроме этого возможно например использовать socat в режиме TCP-LISTEN сервера, и вообще подключаться извне через утилиту telnet к виртуальной машине.

К списку статей

 

Интересуюсь по большей части системным анализом программного обеспечения: поиском багов и анализом неисправностей, а также системным программированием (и не оставляю надежд запилить свою операционку, хотя нехватка времени сказывается :) ). Программированием увлекаюсь с 12 лет, но так уж получилось, что стал я инженером.

Основная сфера моей деятельности связана с поддержкой Solaris и оборудования Sun/Oracle, хотя в последнее время к ним прибавились технологии виртуализации (линейка Citrix Xen) и всякое разное от IBM - от xSeries до Power. Учусь на кафедре Вычислительной Техники НИУ ИТМО.

See you...out there!

http://www.facebook.com/profile.php?id=100001947776045
https://twitter.com/AnnoyingBugs

Ничего не найдено. n is 0