Desligando todas as VMs do VirtualBox (vagrant) em um comando bash fácil de usar (que pode ser colocado em um arquivo bash)

70

Eu uso vagabundo para o desenvolvimento. Eu esqueço de desligar algumas das VMs. Quando vou sair da minha máquina host, o processo de desligamento do Ubuntu parece travar.

Pode haver uma maneira de criar um script para fechar todas as caixas vagabundas com um pouco de comando-fu? Algo como o seguinte, mas algo que, bem, funciona.

for f in $HOME/vagrant;
do;
  cd $f
  vagrant halt
done;
Rick
fonte
Eu não sei vagabundo, mas parece estar vinculado ao VMWare, não ao VirtualBox. Você está realmente usando o VirtualBox?
terdon
@terdon: o Vagrant suporta apenas o Vbox inicialmente. Eu acho que eles suportam agora outro tipo de formatos de VM (entender VMWare)
Sylvain Pineau
@SylvainPineau ah, OK. Acabei de dar uma olhada rápida na página deles e vi um link de "integração VMWare" e assumi. Obrigado pelo esclarecimento.
terdon
11
Eu daria uma olhada neste script . A postagem completa do blog está aqui . Não testado #
Sylvain Pineau
Richard, por favor, não edite a resposta na sua pergunta. Você é livre para responder sua própria pergunta em uma resposta separada. Eu te dei um voto positivo por uma boa pergunta.
don.joey

Respostas:

91

Para um controle programável das máquinas do Virtual Box, podemos usar os comandos VBoxManage :

  • Listar máquinas em execução (retorna nome e UUID):

    VBoxManage list runningvms
    
  • Pare de executar VMs "hibernando" elas (recomendado para evitar a perda de dados)

    VBoxManage controlvm <name|uuid> savestate
    
  • Poweroff executando VMs (não recomendado, pois podemos perder dados no convidado)

    VBoxManage controlvm <name|uuid> poweroff
    
  • Use a ACPI em um sistema operacional convidado compatível com a ACPI (preferível poweroffpara o desligamento normal dos convidados)

    VBoxManage controlvm <name|uuid> acpipowerbutton
    

Consulte também: Como encerrar com segurança o SO convidado no VirtualBox usando a linha de comando

Atualização do OP

Com base nesta resposta correta selecionada abaixo, adicionamos este script bash " $HOME/bin/stop-vagrant.sh". Portanto, agora eu tenho algo que pode iniciar com segurança uma parada de todas as VMs vagantes que eu poderia ter ativado e ainda esquecido em uma sessão.

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

Comando explicado:

vboxmanage list runningvms | - obtém uma lista de todos os vms em execução no VirtualBox

sed -r 's/.*\{(.*)\}/\1/' | - reduz a string até o número de identificação

xargs -L1 -I {} VBoxManage controlvm {} savestate - executa o comando salvar estado em cada caixa que está aberta.

Em xargs

  • -L1 - pegue uma linha de cada vez
  • -I {} - usa {} como um espaço reservado para o próximo comando
Takkat
fonte
Whoo Hoo! Dado o conselho acima, esta linha de comando funciona como mágica: vboxmanage list runningvms | sed -r 's /.* \ {(. *) \} / \ 1 /' | xargs -L1 -I {} VBoxManage controlvm {} savestate
Rick
11
Observe que a -ropção é exclusiva do GNU Sed.
George V. Reilly
Melhor one-liner mágico que eu já vi há algum tempo! Bom trabalho! : D
tftd 28/04
11
No OSX / macOS, você precisará usar em -Evez de -r. É o sinalizador para usar expressões regulares estendidas.
JayD3e
22

A outra resposta é ótima para manipular o Virtualbox, mas o Vagrant possui seus próprios mecanismos para manipular as Máquinas Virtuais e, como foi mencionado em um dos comentários, ele suporta mais do que apenas o VirtualBox, apenas o VMWare no momento, mas quem sabe depois!

Isso parece funcionar para mim:

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

Nota:

Isso funciona com as versões do Vagrant após a versão 1.6. Para versões mais antigas, você provavelmente deve atualizar, mas se não puder, uma das outras opções focadas no Virtualbox pode ser melhor.

ThomasRedstone
fonte
4
esta é obviamente uma resposta muito mais correta (tm). @ Richard deve considerar aceitar esta vez
nhed
O global-statuscomando foi introduzido no Vagrant 1.6 . Os usuários de versões mais antigas do Vagrant, particularmente aqueles que o instalaram via apt-gete ainda podem estar na 1.4.3, precisarão atualizar a instalação do Vagrant antes de poder usar este comando.
Curtis Gibby
11
O BSD xargsnão suporta -r, portanto você pode instalar gxargsvia brewe usá-lo.
kenorb
11

Meu mecanismo para isso:

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

  • status global lista todas as caixas
  • filtre isso para linhas que contêm virtualbox( filtra o texto de ajuda, será interrompido se você estiver usando outro provedor)
  • Filtre isso para exibir apenas os 9 primeiros caracteres (o ID exclusivo global)
  • Embora ainda possamos ler uma linha dessa entrada, leia-a como a variável $ line, em seguida:
    • Imprima essa linha $
    • executar vagrant halt $lineinterrompendo o vagabundo para esse ID exclusivo global

Isso é melhor do que o método Virtualbox acima, porque também executará mecanismos de desligamento vagrantes.

Aquarion
fonte
3
Este comando também funciona para hosts do OS X. Outros falham devido a diferenças nos argumentos da linha de comando que tratam entre as versões OSX e Linux de sede awk. Obrigado!
Andrew Андрей Листочкин
@ AndrewАндрейЛисточкин Confirmar - funciona bem no OS X 10. Não testado em outro sistema operacional embora.
Setevoy
2
O comando acima tenta interromper todas as caixas, não importa se estão em execução ou não, demorando muito tempo para ser executado. Para mim, como eu só uso o virtualbox, mudei o grep "virtualbox" para "running", para obter apenas os que estão em execução.
Alex2php
Essa é uma boa resposta, mas você pode usar em vagrant suspendvez de vagrant haltsalvar o estado e suspendê-lo para uma operação mais rápida e mais rápida.
David Thomas
Verdade, e se funcionar para você, isso é ótimo. Eu tive grandes problemas de cronometragem com VMs suspensas no Virtualbox, por isso não recomendaria.
Aquarion
5

Caso outras pessoas cheguem a esta pergunta: Para quem usa o VirtualBox, ele já pode resolver isso, envolve apenas a edição de um arquivo:

# 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

A vantagem é que não é necessário editar / criar nenhum logout ou init.dstript para executar os comandos publicados nas outras respostas. A desvantagem é que esta solução é específica do VirtualBox.

Testado no Ubuntu 14.10 com VirtualBox 4.3.18.

Todo o crédito vai para este post .

Armando Pérez Marqués
fonte
5

Combinando algumas das outras respostas, isso fechará todas as caixas vagrant do virtualbox em execução:

vagrant global-status | awk '/virtualbox running/{ print $1 }' | xargs vagrant halt
Ryan
fonte
Isso funcionou para mim!
Dayron Gallardo 31/01
3

Eu apenas uso vagrant halt. Se você executá-lo sem mais argumentos, ele interromperá todas as máquinas definidas no arquivo Vagrantfile.

nomenclatura
fonte
1

Se você estiver escrevendo scripts para analisar comandos do Vagrant, é recomendável analisar a saída amigável à máquina ( --machine-readable), que é mais consistente.

O formato é:

timestamp,target,type,data...

para que você possa importá-lo como arquivo CSV, pois é separado por vírgula.

Com o shell, provavelmente é mais difícil de analisar, por exemplo:

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

Consulte: Vagrant - Saída legível por máquina


No entanto, acho mais fácil analisar a saída padrão, por exemplo,

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

Btw. Teoricamente, o vagrantcomando deve aceitar uma expressão regular para a lista de VMs a serem suspensas conforme esta postagem do GH , por exemplo:

vagrant suspend '*'

mas não funciona e há um bug # 7221 pendente para corrigi-lo.


Bilhetes GitHub relacionados:

kenorb
fonte
0

Isso pode ou não funcionar para você ;-) Funciona para mim

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
Brad Parks
fonte