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

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

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

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

11 ответов

Решение

Для управления сценариями машин 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 {} - использует {} в качестве заполнителя для следующей команды

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

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

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

Замечания:

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

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

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.

В случае, если другие люди дойдут до этого вопроса: для тех, кто использует 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.

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

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

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

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

Если вы пишете сценарии для анализа команд 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:

Вот подборка рабочих однострочников по состоянию на сентябрь 2020 года. Спасибо всем предыдущим авторам за вдохновение.

Остановить все бродячие коробки

Версия 1 (короче)

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

Версия 2 (более надежная)

Совместимость с macOS/BSD:

vagrant global-status --machine-readable | cut -d, -f5 | grep -B3 running | egrep -o '[0-9a-f]{7}' | xargs -n 1 -- vagrant halt

Совместимость с GNU:

vagrant global-status --machine-readable | cut -d, -f5 | grep -B3 running | egrep -o '[0-9a-f]{7}' | xargs -r -d '\n' -n 1 -- vagrant halt

Псевдоним

Вы можете добавить это к псевдониму для быстрого выполнения. Добавьте этот код в~/.bashrc, ~/.zshrc или эквивалент вашей оболочки.

Пример macOS/BSD:

alias vagrantHaltAll="vagrant global-status --machine-readable | cut -d, -f5 | grep -B3 running | egrep -o '[0-9a-f]{7}' | xargs -n 1 -- vagrant halt"

# Usage:
vagrantHaltAll

Подвесьте все бродячие коробки

Или если вы хотите suspend на любых запущенных машинах синтаксис прост:

vagrant suspend --all

Я рекомендую использовать haltдля веб-серверов; это экономит место на диске и может быть быстрее.

Потому что vagrant haltтребуются метаданные виртуальной машины (вы запускаете ее в каталоге с файлом Vagrantfileи каталог .vagrant) его нельзя легко использовать для остановки всех виртуальных машин.

В некоторых случаях достаточно остановить все VBox:

      myvbox-halt-all() {
  VBoxManage list runningvms |& tr -d '\r' | while read name uuid; do
    VBoxManage controlvm "$uuid" acpipowerbutton
  done
}

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

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

vagrant global-status | grep virtualbox | cut -c 1-9 | xargs vagrant suspendприостановит работу всех машин, созданных Vagrant.

Другие вопросы по тегам