Как автоматически запускать и выключать машины VirtualBox?

52

Мне нужно запустить систему программного обеспечения, которая предназначена для установки в качестве устройства на выделенном компьютере. Чтобы сэкономить энергию, я планирую запустить систему на виртуальной машине VirtualBox.

Хост - это стандартная Linux-система с системой SysV-Init, гостем является сильно модифицированный Linux, и я бы предпочел не менять его дальше. VirtualBox используется в версии OSE.

Я уже разобрался, как запустить виртуальную машину при загрузке хоста ( Edit: это делается, как Никхил упоминал ниже, с помощью команды VBoxManager startvm), но как я могу корректно завершить работу VM? Любой скрипт, работающий на хосте, должен будет ждать, пока гость полностью не отключится.

Кто-нибудь может подсказать, как, например, должен выглядеть сервисный файл, делающий это?

jstarek
источник
не могли бы вы дать сценарий запуска для запуска виртуальной машины во время загрузки
Beginner

Ответы:

34

Вы пробовали acpipowerbuttonиз этого набора команд?

VBoxManage controlvm        <uuid>|<name>
                            pause|resume|reset|poweroff|savestate|
                            acpipowerbutton|acpisleepbutton|

Редактировать после прочтения комментариев:

Вы можете использовать acpidили другие утилиты acpi, чтобы сделать его изящным. Кроме того, можете ли вы предоставить больше информации о том, как вы выключаете машину в данный момент?

Равнина shutdownне будет ждать незавершенных работ, задержка может быть слишком большой.

Я предполагаю, что вы не используете оконный менеджер, поэтому попробуйте этот инструмент.

Просто видел этого демона . Вы можете найти это полезным.

Мавроматис Лозай
источник
Спасибо за ваш ответ и добро пожаловать на unix.stackexchange.com! Тем не менее, я боюсь, что ваш ответ также не решает мою проблему: acpipowerbutton имитирует нажатие кнопки питания на реальной машине, но после выполнения этой команды на хосте виртуальной машине, опять же, потребуется некоторое время для выключения.
Jstarek
4
Конечно. Таким образом, вы должны написать цикл, который проверяет, работает ли виртуальная машина. ACPI - точно такой же метод, который я использую в своих сценариях для этого. vboxmanage list runningvmsпока ваша ВМ не исчезнет.
Нильс
Хорошо, хотя я думаю, что на практике я соглашусь на упаковку управления, +50 к вам за указание на начальный текст!
Jstarek
16

Вместо того, чтобы кодировать это самостоятельно, рассмотрите возможность использования Vagrant , который создан для создания экземпляров и управления экземплярами виртуальных ящиков. Документация отличная, и я предлагаю вам проверить ее, а не пытаться накатить свою.

Суть в том, что вы создаете простой управляющий файл, а затем запускаете vagrant upдля запуска столько экземпляров VirtualBox, сколько хотите. Вы можете использовать vagrant sshдля входа в хосты и vagrant haltвыключить хост (без завершения). vagrant destroyизбавится от экземпляров.

Он поддерживает инициализацию с помощью Puppet, Ansible или Chef и позволяет вам контролировать большинство выставленных настроек конфигурации VBox.

Аарон Браун
источник
2
Я фанат бродяги, но в таком случае, зачем тебе это? OP запускает устройство, а не создает свою собственную систему, поэтому подготовка полностью пропускает суть. И зачем идти и делать из устройства нестандартную «коробку», просто чтобы использовать vagrant, когда вы в основном проходите процесс сборки системы с виртуальной коробкой для этого?
mc0e
10

У меня есть такое же приложение, как у вас, с одним отличием: мне нужно перезагрузить систему и восстановиться из снимка.

То, что вас интересует, это безголовый режим .

У меня есть несколько таких служб, поэтому я использую следующий скрипт:

VBox_StopRestoreStart.sh

#!/bin/bash
if [ -z "$1" ]; then
        echo "Usage: $0 VMNAME_or_UUID"
        exit 1
fi
set -x
VBoxManage controlvm  "$1" poweroff  #enforce turnoff
VBoxManage snapshot   "$1" restorecurrent   #retore state
VBoxManage showvminfo "$1" | grep State   #display state to ensure
VBoxHeadless -s       "$1"  #run in headless mode in background

как я могу изящно выключить ВМ?

Если вы хотите отключить виртуальную машину, у вас есть два варианта, в зависимости от вашего приложения:

  • Эмулируйте «кнопку выключения» или «спящую кнопку» и подготовьте виртуальную машину, чтобы она отреагировала на нее (изящно закрылась)
    • VBoxManage controlvm <uuid>|<VMname> acpipowerbutton
    • VBoxManage controlvm <uuid>|<VMname> acpisleepbutton
  • Сохранить состояние ВМ, чтобы потом восстановить
    • VBoxManage controlvm <uuid>|<VMname> savestate

СОВЕТЫ: ​​Вы можете найти полезное:

  • VBoxManage list vms - список доступных vms
  • rdesktop IP-ADDR:3389или rdesktop-vrdp IP-ADDR:3389- когда вам нужен графический интерфейс (даже удаленно ), когда вы работаете в автономном режиме:VBoxHeadless -s <uuid>|<VMname>
  • VBoxManage startvm - начать с графического интерфейса для локальной отладки

Соответствующая глава руководства VirtualBox: Глава 7. Удаленные виртуальные машины. Шаг за шагом: создание виртуальной машины на автономном сервере

PS Если вы заинтересованы в полнофункциональных уже реализованных решениях, OpenStack кажется интересным выбором.

Гжегож Вежовецкий
источник
10

Изучите документацию по управлению виртуальными машинами VirtualBox по адресу http://www.virtualbox.org/manual/ch08.html.

Для вывода списка виртуальных машин используйте команду VBoxManage list vms

Для запуска ВМ используйте команду VBoxManage startvm

http://www.virtualbox.org/manual/ch08.html#vboxmanage-controlvm

Для управления ВМ используйте VBoxManage controlvm

controlvmСубкоманда позволяет изменить состояние виртуальной машины , которая в настоящее время работает. Можно указать следующее:

VBoxManage controlvm <vm> pauseвременно приостанавливает работу виртуальной машины, не изменяя ее состояние навсегда. Окно виртуальной машины будет окрашено в серый цвет, чтобы указать, что виртуальная машина в данный момент приостановлена. (Это эквивалентно выбору пункта «Пауза» в меню «Машина» GUI.)

Используйте VBoxManage controlvm <vm> resumeдля отмены предыдущей команды паузы. (Это эквивалентно выбору пункта «Возобновить» в меню «Машина» GUI.)

VBoxManage controlvm <vm> resetна виртуальной машине действует так же, как нажатие кнопки «Сброс» на реальном компьютере: холодная перезагрузка виртуальной машины, которая немедленно перезапустит и снова загрузит гостевую операционную систему. Состояние виртуальной машины не сохраняется заранее, и данные могут быть потеряны. (Это эквивалентно выбору пункта «Сброс» в меню «Машина» GUI.)

VBoxManage controlvm <vm> poweroffдействует на виртуальную машину так же, как и на кабель питания на реальном компьютере. Опять же, состояние виртуальной машины не сохраняется заранее, и данные могут быть потеряны. (Это эквивалентно выбору пункта «Закрыть» в меню «Машина» графического интерфейса или нажатию кнопки закрытия окна, а затем выбору «Выключить машину» в диалоговом окне.)

После этого состояние виртуальной машины будет отключено.

Никхил Мулли
источник
Обратите внимание, что в некоторых системах это так vboxmanage(все в нижнем регистре).
Arcege
2
Спасибо за ваш ответ, но, к сожалению, это не решает мою проблему: мне нужно изящно завершить работу гостя, т. Е. Выполнить «shutdown -h now» внутри гостевой системы и попросить хост подождать, пока гость полностью не выключится. Ни одна из VBoxManage controlvmподкоманд не делает этого.
Jstarek
Вы можете убедиться, что, перепроверив все vms, не работают на хосте, прежде чем хост выйдет из строя. Если вам нужно управлять хостом изнутри гостя, то virtualbox.org/manual/ch08.html#vboxmanage-guestcontrol, но это может не дать вам того, что вы ищете. Вы должны написать скрипт запуска, такой как /etc/init.d/vboxvms-serviceскрипт, на хост-системе, который при запуске включит все vms и после остановки заставит все vms выключиться.
Nikhil Mulley
VBoxManage controlvm savestateЭто еще одна возможность (по крайней мере, Google говорит мне), она сохраняет состояние компьютеров и корректно завершает работу, но по-прежнему не может заставить хост ждать.
Баарн
5

Для системной системы вы можете попробовать это.

Шаг № 1: создать сервисный файл

[Unit]
Description=VBox Virtual Machine %i Service
Requires=systemd-modules-load.service
After=systemd-modules-load.service

[Service]
User=user
Group=vboxusers
ExecStart=/usr/bin/VBoxHeadless -s %i
ExecStop=/usr/bin/VBoxManage controlvm %i savestate

[Install]
WantedBy=multi-user.target

Шаг № 2: Включить служебный файл

$ sudo systemctl enable vboxvmservice@vm_name.service

Рекомендации

Ян Рюэг
источник
1
Здесь желательно включить ответ и при необходимости предоставить ссылки на более подробную информацию. Цели ссылок исчезают без уведомления, что делает ваш ответ бесполезным.
Антон
Ну, проблема в том, что я не могу скопировать весь файл systemd в ссылке 1 здесь, или я должен это сделать?
Ян Рюегг
Что ж, к сожалению, «гниение ссылок» в этих случаях является огромной проблемой ... Я думаю, что для потомков следующие две строки улавливают основную идею вашей ссылки: она создает сервис, который использует VBoxHeadless -s %iдля запуска и VBoxManage controlvm %i savestateостановки виртуальной машины.
Jstarek
Попробовал это в Debian Jessie, но это не сработало. Создал пользователя и группу, установил владение всеми файлами (включая / dev / vbox *). Но когда служба запускается, она не может найти виртуальную машину, даже если имя верное. Будет использовать обычный скрипт инициализации в конце концов.
MIVK
3

Как насчет отправки команды через ssh с хоста на гостя?

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

Baarn
источник
Хорошая мысль, но это гарантирует, что гостевая виртуальная машина будет доступна через сеть с хоста, по крайней мере, через порт ssh (22).
Nikhil Mulley
По сути, это будет работать, устройство может быть доступно во всей локальной сети через его DNS-запись. Однако предположим, что я написал сценарий, который ssh'd в устройстве всякий раз, когда хост отключается - ему все равно придется блокировать (пауза), пока гость не отключится полностью. Именно в этом и заключается мой вопрос: как сценарий может узнать, когда гость отключен, чтобы он мог вернуть поток управления обратно в SysV-Init, и хост мог продолжать отключаться?
Jstarek
1
Ваш комментарий предполагает, что все будет работать гладко на хост-системе, а не на гостевой системе. Что, если кабель питания подключен к хост-системе? Это другое обсуждение. Ваш SysV-init в хост-системе будет ждать, пока сценарий службы остановит виртуальные машины, если сценарий службы понимает логику правильного отключения гостевых виртуальных машин (отключение на удаленном хосте или просто отключение через интерфейс vbox) и затем yield возвращает статус успеха или ошибки обратно на консоль или в init.
Nikhil Mulley
1
Относительно того, как скрипт знает, когда гость выключен, попробуйте просто проверить, включен или выключен виртуальный компьютер из интерфейса VboxManager и гость ли ssh'able. Кроме того, поместите некоторый мониторинг в хост-систему, который будет выполнять проверку доступности виртуальной машины из Vboxmanager и ее ssh'able на своевременной основе.
Nikhil Mulley
1

Мое решение: в этом сценарии оболочки «root» является инициатором, а «theuser» является владельцем «thevm»

Я знаю, что vms закончился, когда выходные данные команды VBoxManage list runningvmsвозвращают пустую строку.

...
start(){
    su -c "VBoxHeadless --startvm thevm" -s /bin/bash theuser &
    # maybe another vbox command
}

stop(){
    su -c "VBoxManage controlvm thevm acpipowerbutton" -s /bin/bash theuser
    # maybe another vbox command
    while [ "`su -c 'VBoxManage list runningvms' -s /bin/bash theuser`" != "" ]
    do
        echo waiting for VMs to shutdown
        sleep 3
    done
}
...
Хорхе Санчес
источник
1

Для запуска vm:

VBoxManage startvm VMNAME --type headless

Чтобы остановить ВМ:

VBoxManage controlvm VMNAME savestate

Список всех запущенных виртуальных машин:

VBoxManage list runningvms
RIT
источник
0

Может быть, это поможет как часть решения.

VBoxManage list runningvms | tr -s '\" {' '%{' | cut -d '%' -f3  | while read uuid; do
   VBoxManage controlvm $uuid savestate; 
done
user58380
источник
0

Почему бы вам не войти в свой гость и не отключиться оттуда?

Если у вас нет веской причины не устанавливать sshd и не получать доступ к виртуальной машине через VBox, я бы выбрал скрипт, который просто выдает ssh shutdown -h now. Если честно, я бы создал скрипт для каждой машины, который правильно выключит его и проведет некоторые проверки на нем.

Просто упакуйте /etc/init.d/shutdown_vm скрипт, который вызывает другой с хоста, вызов будет блокирован, пока не будет готов. Этот процесс (как описано) добавляет зависимость linux на гостя, но удаляет зависимость VBox на хосте.

Сокращение к погоне: вам не нужен доступ к VBox для выключения компьютера, если у вас есть какие-то средства доступа к нему (например, ssh), то ОС всегда будет иметь для этого какие-то средства (включение, разумеется, другое)

estani
источник
Две причины: во-первых, как было указано в исходном вопросе, я не хотел менять сильно модифицированные гостевые ОС, если в этом не было необходимости. Во-вторых, и что более важно, это было предназначено для обеспечения чистого способа автоматического выключения всех работающих виртуальных машин, если хост был выключен.
Jstarek
@jstarek Но вам не нужно изменять гостевую ОС, если вы этого не хотите (99,99% времени у вас есть какие-то средства для входа или это исключение). И именно в этом и заключается идея: если хост выйдет из строя, при изменении времени выполнения будет вызван соответствующий скрипт, который просто регистрирует гостя и закрывает его из «изнутри», что в любом случае делает vagrant ... перед тем, как перейти к "грубому" сила "это ...
estani