Выключение всех виртуальных машин VirtualBox (vagrant) одной простой в использовании командой bash (которая может быть помещена в файл bash)


70

Я использую бродягу для разработки. Я забыл закрыть несколько виртуальных машин. Когда я выхожу из системы на своем хост-компьютере, процесс завершения работы Ubuntu зависает.

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

for f in $HOME/vagrant;
do;
  cd $f
  vagrant halt
done;

Я не знаю vagrant, но, похоже, он связан с VMWare, а не с VirtualBox. Вы на самом деле используете VirtualBox?
Terdon

@terdon: Vagrant изначально поддерживал только Vbox. Я думаю, что они теперь поддерживают другие типы форматов VM (понимают VMWare)
Сильвен Пино,

@SylvainPineau ах, хорошо. Я просто быстро взглянул на их веб-страницу, увидел ссылку «Интеграция с VMWare» и предположил. Спасибо за разъяснения.
Terdon

1
Я бы посмотрел на этот сценарий . Полный пост в блоге здесь . Не проверено
Сильвен Пино,

Ричард, пожалуйста, не редактируйте ответ на свой вопрос. Вы можете ответить на свой вопрос в отдельном ответе. Я задал вам хороший вопрос.
don.joey

Ответы:


91

Для управления сценариями машин Virtual Box мы можем использовать команды VBoxManage :

  • Список запущенных машин (возвращает имя и UUID):

    VBoxManage list runningvms
    
  • Прекратите работу виртуальных машин, «спячки» их (рекомендуется, чтобы избежать потери данных)

    VBoxManage controlvm <name|uuid> savestate
    
  • Poweroff работает виртуальные машины (не рекомендуется, потому что мы можем потерять данные в гостевой)

    VBoxManage controlvm <name|uuid> poweroff
    
  • Использовать ACPI в гостевой ОС с поддержкой ACPI (предпочтительно poweroffдля корректного отключения гостей)

    VBoxManage controlvm <name|uuid> acpipowerbutton
    

Также смотрите: Как безопасно завершить работу гостевой ОС в VirtualBox с помощью командной строки

Обновление от ОП

Основываясь на этом правильном ответе ниже, я добавил этот скрипт bash " $HOME/bin/stop-vagrant.sh". Так что теперь у меня есть кое-что, что может безопасно начать остановку всех бродячих виртуальных машин, о которых я, возможно, уже говорил, но которые забыли в сеансе.

vboxmanage list runningvms | sed -r 's/.*\{(.*)\}/\1/' | xargs -L1 -I {} VBoxManage controlvm {} savestate

Команда объяснила:

vboxmanage list runningvms | - получает список всех запущенных vms под VirtualBox

sed -r 's/.*\{(.*)\}/\1/' | - обрезает строку до идентификатора

xargs -L1 -I {} VBoxManage controlvm {} savestate - запускает команду сохранения состояния в каждом открытом окне.

На xargs

  • -L1 - взять по одной строке за раз
  • -I {} - использует {} в качестве заполнителя для следующей команды

Уууууууууууууууууууууууу! Учитывая приведенный выше совет, эта командная строка работает волшебно: vboxmanage list runningvms | sed -r 's /.* \ {(. *) \} / \ 1 /' | xargs -L1 -I {} VBoxManage controlvm {} savestate
Рик

1
Обратите внимание, что эта -rопция уникальна для GNU Sed.
Джордж В. Рейли

Лучший волшебный однострочник, который я когда-либо видел! Отличная работа! : D
TFTD

1
В OSX / macOS вам нужно использовать -Eвместо -r. Это флаг использования расширенных регулярных выражений.
JayD3e

22

Другой ответ хорош для работы с Virtualbox, но Vagrant имеет свои собственные механизмы для работы с виртуальными машинами, и, как было упомянуто в одном из комментариев, он поддерживает не только VirtualBox, только VMWare на данный момент, но кто знает позже!

Кажется, это работает для меня:

vagrant global-status | awk '/running/{print $1}' | xargs -r -d '\n' -n 1 -- vagrant suspend

Примечание:

Это работает с версиями Vagrant после 1.6, для более старых версий вам, вероятно, следует обновить, но если вы не можете, один из других вариантов, который фокусируется на Virtualbox, может быть лучше.


4
это, очевидно, намного корректирующий (тм) ответ. @Richard должен рассмотреть возможность принятия этого вместо этого
nhed

Команда global-statusбыла введена в Vagrant 1.6 . Пользователи более старых версий Vagrant, особенно те, которые установили его через apt-getи, возможно, все еще используют 1.4.3, должны будут обновить свою установку Vagrant, прежде чем они смогут использовать эту команду.
Кертис Гибби

1
BSD xargsне поддерживает -r, поэтому вы можете установить gxargsчерез brewи использовать его вместо.
Кенорб

11

Мой механизм для этого:

vagrant global-status | grep virtualbox | cut -c 1-9 | while read line; do echo $line; vagrant halt $line; done;

  • глобальный статус перечисляет все ящики
  • Фильтровать это для строк, содержащих virtualbox(Отфильтровывает текст справки, сломается, если вы используете какой-либо другой поставщик)
  • Фильтр для отображения только первых 9 символов (глобальный уникальный идентификатор)
  • Хотя мы все еще можем прочитать строку из этого ввода, прочитайте ее как переменную $ line:
    • Распечатайте эту строку $
    • запустить vagrant halt $lineостановить бродяги для этого глобального уникального идентификатора

Это лучше, чем метод Virtualbox, описанный выше, потому что он также будет запускать любые механизмы выключения, настроенные с помощью vagrant.


3
Эта команда работает и для хостов OS X. Другие терпят неудачу из-за различий в обработке аргументов командной строки между версиями OSX и Linux sedи awk. Спасибо!
Андрей Андрей Листочкин

@ AndrewАндрейЛисточкин Подтвердите - работает на OS X 10 хорошо. Не проверяется на других ОС, хотя.
Сетевой

2
Вышеприведенная команда пытается остановить все блоки, независимо от того, запущены они или нет, поэтому выполнение занимает много времени. Для меня, поскольку я использую только virtualbox, я изменил grep «virtualbox» на «running», чтобы получить только запущенные.
Alex2php

Это хороший ответ, но вы можете использовать его vagrant suspendвместо того, vagrant haltчтобы сохранять состояние и приостанавливать работу для ускорения спада и повышения.
Дэвид Томас

Правда, и если это работает для вас, это здорово. У меня были серьезные проблемы с хронометрированием приостановленных виртуальных машин в Virtualbox, поэтому я бы не рекомендовал это делать.
Акварион

5

В случае, если другие люди дойдут до этого вопроса: для тех, кто использует VirtualBox, он уже может позаботиться об этом, только включает в себя редактирование файла:

# Contents of /etc/default/virtualbox
# ...
# ...
# SHUTDOWN_USERS="foo bar"  
#   check for running VMs of user 'foo' and user 'bar'
#   'all' checks for all active users
# SHUTDOWN=poweroff
# SHUTDOWN=acpibutton
# SHUTDOWN=savestate
#   select one of these shutdown methods for running VMs
#   acpibutton and savestate causes the init script to wait
#   30 seconds for the VMs to shutdown

## My original values
# SHUTDOWN_USERS=""
# SHUTDOWN=poweroff

## My current values
SHUTDOWN_USERS="all"
SHUTDOWN=savestate

init.dПоложительным моментом является то, что нет необходимости редактировать / создавать любой выход из системы или выполнять команды, опубликованные в других ответах. Недостатком является то, что это решение относится к VirtualBox.

Протестировано на Ubuntu 14.10 с VirtualBox 4.3.18.

Весь кредит идет на этот пост .


5

Комбинируя некоторые другие ответы, это закроет все запущенные виртуальные ящики бродяги:

vagrant global-status | awk '/virtualbox running/{ print $1 }' | xargs vagrant halt

Это сработало для меня!
Дайрон Галлардо

3

Я просто использую vagrant halt. Если вы запустите его без дополнительных аргументов, он остановит все машины, определенные в Vagrantfile.


1

Если вы пишете сценарии для анализа команд Vagrant, рекомендуется проанализировать машинно-ориентированный вывод ( --machine-readable), который является более последовательным.

Формат такой:

timestamp,target,type,data...

так что вы можете импортировать его как файл CSV, так как он разделен запятыми.

С shell, возможно, труднее разобрать, например:

for id in $(vagrant global-status --machine-readable | cut -d, -f5 | grep -B3 running | egrep -o "[0-9a-f]{7}"); do
    vagrant suspend $id;
done

См .: Vagrant - Машиносчитываемый вывод


Однако мне легче разобрать стандартный вывод, например

while read id name provider state path; do
  [ "$state" = "running" ] && vagrant suspend $id;
done < <(vagrant global-status)

Btw. Теоретически vagrantкоманда должна принимать регулярное выражение для списка виртуальных машин , чтобы приостановить в соответствии с настоящим GH пост , например:

vagrant suspend '*'

но это не работает, и есть ошибка # 7221, которая находится на рассмотрении, чтобы исправить это.


Связанные билеты GitHub:


0

Это может или не может работать для вас ;-) Работает для меня

vagrant_halt_all.sh

#!/usr/bin/env bash
if [ -z "$1" ]
then
  OPTS=""
else
  # force close if any arg passed
  OPTS="-f"
fi

for i in $(vagrant global-status | grep running | awk '{print $1}'); do 
  DIR=$(vagrant global-status | grep running | awk '{print $5}')
  cd "$DIR";
  OUT=$(vagrant halt);
  echo "attempted to halt $i: $OUT"
done
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.