Вимкнення всіх VM VirtualBox (бродячих) в одній простій у користуванні команді bash (яку можна помістити у файл bash)


70

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

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

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

Я не знаю бродячого, але, схоже, він пов'язаний з VMWare, а не з VirtualBox. Ви фактично використовуєте VirtualBox?
terdon

@terdon: Vagrant спочатку підтримував лише Vbox. Я думаю, вони зараз підтримують інші типи форматів VM (зрозумійте VMWare)
Sylvain Pineau,

@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". Тож тепер у мене є щось, що може безпечно почати зупинку всіх бродячих VM, про які я, можливо, увімкнув би ще забуте під час сеансу.

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і використовувати його замість цього.
kenorb

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, описаний вище, тому що він також буде запускати будь-які бродячі налаштовані механізми відключення.


3
Ця команда працює і для хостів OS X. Інші зазнають невдачі з -за відмінності в параметрах командного рядка обробки між OSX і Linux версій з sedі awk. Дякую!
Андрій Андрей Листочкин

@ AndrewАндрейЛисточкин Підтвердити - працює на ОС X 10 добре. Хоча не тестується на інших ОС.
сетевий

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

Це хороша відповідь, але ви, можливо, хочете використовувати vagrant suspendзамість того, vagrant haltщоб зберегти стан і призупинити, щоб швидше вниз і вгору.
Девід Томас

Щоправда, і якщо це працює для вас, це чудово. У мене виникли масові проблеми з тимчасовим зберіганням призупинених VM під 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, оскільки він розділений комами.

З оболонкою, мабуть, складніше розібратися, наприклад:

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.