Herunterfahren aller VirtualBox (vagrant) -VMs mit einem benutzerfreundlichen Bash-Befehl (der in eine Bash-Datei eingefügt werden kann)

70

Ich benutze Vagrant für die Entwicklung. Ich habe vergessen, einige der VMs herunterzufahren. Wenn ich mich von meinem Host-Computer abmelden möchte, scheint der Ubuntu-Shutdown-Prozess zu hängen.

Könnte es eine Möglichkeit geben, das Schließen aller Vagrant-Boxen mit ein bisschen Kommandozeilen-Fu zu skripten? Etwas wie das Folgende, aber etwas, das gut funktioniert.

for f in $HOME/vagrant;
do;
  cd $f
  vagrant halt
done;
Rick
quelle
Ich kenne Vagrant nicht, aber es scheint mit VMWare verbunden zu sein, nicht mit VirtualBox. Verwenden Sie tatsächlich VirtualBox?
Terdon
@terdon: Vagrant unterstützt anfangs nur Vbox. Ich denke, sie unterstützen jetzt andere Arten von VM-Formaten (verstehen VMWare)
Sylvain Pineau
@ SylvainPineau ah, OK. Ich hatte gerade einen kurzen Blick auf ihre Webseite und sah einen "VMWare-Integration" -Link und vermutete. Danke für die Klarstellung.
Terdon
1
Ich würde mir dieses Skript ansehen . Der vollständige Blogbeitrag ist hier . Nicht getestet
Sylvain Pineau
Richard, bitte bearbeite die Antwort in deiner Frage nicht. Sie können Ihre eigene Frage in einer separaten Antwort beantworten. Ich habe dich für eine gute Frage positiv bewertet.
don.joey

Antworten:

91

Für eine skriptfähige Steuerung von Virtual Box-Maschinen können wir die VBoxManage- Befehle verwenden:

  • Laufende Maschinen auflisten (Name und UUID zurückgeben):

    VBoxManage list runningvms
    
  • Beenden Sie die Ausführung von VMs durch "Ruhezustand" (empfohlen, um Datenverlust zu vermeiden)

    VBoxManage controlvm <name|uuid> savestate
    
  • Ausschalten von VMs (nicht empfohlen, da möglicherweise Daten im Gast verloren gehen)

    VBoxManage controlvm <name|uuid> poweroff
    
  • Verwenden Sie ACPI in einem ACPI-fähigen Gastbetriebssystem (vorzuziehen powerofffür ein ordnungsgemäßes Herunterfahren von Gästen).

    VBoxManage controlvm <name|uuid> acpipowerbutton
    

Siehe auch: So fahren Sie das Gastbetriebssystem in VirtualBox über die Befehlszeile sicher herunter

Update von OP

Basierend auf der unten ausgewählten richtigen Antwort habe ich dieses Bash-Skript " $HOME/bin/stop-vagrant.sh" hinzugefügt . Jetzt habe ich also etwas, mit dem ich sicher anfangen kann, alle vagabundierenden VMs zu stoppen, die ich möglicherweise in einer Sitzung eingeschaltet und doch vergessen habe.

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

Befehl erklärt:

vboxmanage list runningvms | - Ruft eine Liste aller laufenden VMs unter VirtualBox ab

sed -r 's/.*\{(.*)\}/\1/' | - streift die Zeichenfolge bis zur ID-Nummer ab

xargs -L1 -I {} VBoxManage controlvm {} savestate - Führt den Befehl zum Speichern des Status für jede Box aus, die geöffnet ist.

Auf xargs

  • -L1 - Nehmen Sie jeweils eine Zeile
  • -I {} - verwendet {} als Platzhalter für den nächsten Befehl
Takkat
quelle
Whoo Hoo! In Anbetracht der obigen Hinweise funktioniert diese Befehlszeile magisch: vboxmanage list runningvms | sed -r 's /.* \ {(. *) \} / \ 1 /' | xargs -L1 -I {} VBoxManage controlvm {} savestate
Rick
1
Beachten Sie, dass diese -rOption nur bei GNU Sed verfügbar ist.
George V. Reilly
Der beste magische Einzeiler, den ich seit einiger Zeit gesehen habe! Gut gemacht! : D
tftd
1
Unter OSX / macOS müssen Sie -Eanstelle von verwenden -r. Es ist das Flag für die Verwendung von erweiterten regulären Ausdrücken.
JayD3e
22

Die andere Antwort ist großartig für den Umgang mit Virtualbox, aber Vagrant verfügt über eigene Mechanismen für den Umgang mit virtuellen Maschinen und unterstützt, wie in einem der Kommentare erwähnt, mehr als nur VirtualBox, im Moment nur VMWare, aber wer weiß es später!

Das scheint bei mir zu funktionieren:

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

Hinweis:

Dies funktioniert mit Vagrant-Versionen nach 1.6. Für ältere Versionen sollten Sie wahrscheinlich ein Upgrade durchführen. Wenn dies jedoch nicht möglich ist, ist eine der anderen Optionen, die sich auf Virtualbox konzentrieren, möglicherweise besser.

ThomasRedstone
quelle
4
Dies ist offensichtlich eine viel korrektere Antwort. @ Richard sollten diese ein betrachten , anstatt zu akzeptieren
nhed
Der global-statusBefehl wurde in Vagrant 1.6 eingeführt . Benutzer älterer Versionen von Vagrant, insbesondere diejenigen, die Vagrant apt-getüber 1.4.3 installiert haben und möglicherweise noch auf 1.4.3 installiert sind, müssen ihre Vagrant-Installation aktualisieren, bevor sie diesen Befehl verwenden können.
Curtis Gibby
1
BSD xargsunterstützt nicht -r, daher können Sie es gxargsüber installieren brewund stattdessen verwenden.
Kenorb
11

Mein Mechanismus dafür:

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

  • global-status listet alle Felder auf
  • Filter, der für Zeilen enthält virtualbox(Filtert den Hilfetext heraus, wird unterbrochen, wenn Sie einen anderen Anbieter verwenden)
  • Filtern Sie dies, um nur die ersten 9 Zeichen (die globale eindeutige ID) anzuzeigen.
  • Während wir noch eine Zeile von dieser Eingabe lesen können, lesen Sie diese als Variable $ line, dann:
    • Drucken Sie diese $ -Zeile aus
    • laufen vagrant halt $linedie vagabundierenden für die globale eindeutige ID zu stoppen

Dies ist besser als die oben beschriebene Virtualbox-Methode, da dort auch alle vagrant konfigurierten Abschaltmechanismen ausgeführt werden.

Aquarion
quelle
3
Dieser Befehl funktioniert auch für OS X-Hosts. Andere schlagen aufgrund von Unterschieden bei der Behandlung von Befehlszeilenargumenten zwischen OSX- und Linux-Versionen von sedund fehl awk. Vielen Dank!
Andrew Андрей Листочкин
@ AndrewАндрейЛисточкин Bestätigen - funktioniert unter OS X 10 gut. Wird jedoch nicht auf anderen Betriebssystemen getestet.
Setevoy
2
Der obige Befehl versucht, alle Boxen anzuhalten, unabhängig davon, ob sie ausgeführt werden oder nicht. Daher dauert die Ausführung sehr lange. Für mich, da ich nur virtualbox benutze, habe ich das "virtualbox" grep in "running" geändert, um nur die laufenden zu bekommen.
Alex2php
Dies ist eine gute Antwort, aber Sie können gerne verwenden vagrant suspendstatt , vagrant haltum den Zustand zu speichern und für eine schnellere nach oben und unten suspendieren.
David Thomas
Stimmt, und wenn es bei Ihnen funktioniert, ist das großartig. Ich hatte massive Zeitprobleme mit angehaltenen VMs unter Virtualbox, daher würde ich es nicht empfehlen.
Aquarion
5

Falls andere Leute auf diese Frage kommen: Für diejenigen, die VirtualBox verwenden, kann dies bereits erledigt werden, es muss lediglich eine Datei bearbeitet werden:

# 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

Der Vorteil ist, dass es nicht erforderlich ist, sich init.dabzumelden oder zu streifen, um die in den anderen Antworten angegebenen Befehle auszuführen. Der Nachteil ist, dass diese Lösung spezifisch für VirtualBox ist.

Getestet unter Ubuntu 14.10 mit VirtualBox 4.3.18.

Alle Kredite gehen an diesen Beitrag .

Armando Pérez Marqués
quelle
5

Wenn Sie einige der anderen Antworten kombinieren, werden alle laufenden Vagabund-Boxen von virtualbox geschlossen:

vagrant global-status | awk '/virtualbox running/{ print $1 }' | xargs vagrant halt
Ryan
quelle
Das hat bei mir funktioniert!
Dayron Gallardo
3

Ich benutze nur vagrant halt. Wenn Sie es ohne weiteres Argument ausführen, werden alle in der definierten Rechner gestoppt Vagrantfile.

keine Männer
quelle
1

Wenn Sie Skripte schreiben, um Vagrant-Befehle zu analysieren, wird empfohlen, die maschinenfreundliche Ausgabe ( --machine-readable) zu analysieren, die konsistenter ist.

Das Format ist:

timestamp,target,type,data...

Sie können es also als CSV-Datei importieren, da es durch Kommas getrennt ist.

Mit der Shell ist das Parsen wahrscheinlich schwieriger, zum Beispiel:

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

Siehe: Vagrant - Maschinenlesbare Ausgabe


Ich finde es jedoch einfacher, die Standardausgabe zu analysieren, z

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

Btw. Theoretisch vagrantsollte der Befehl einen regulären Ausdruck für die Liste der VMs akzeptieren, die gemäß diesem GH- Post angehalten werden sollen. Beispiel:

vagrant suspend '*'

Aber es funktioniert nicht und es gibt einen Fehler # 7221, der noch aussteht, um ihn zu beheben.


Ähnliche GitHub Tickets:

Kenorb
quelle
0

Das kann bei dir funktionieren oder auch nicht ;-) Funktioniert bei mir

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
quelle