Mematikan semua VM VirtualBox (vagrant) dalam satu perintah bash yang mudah digunakan (yang dapat dimasukkan ke file bash)

70

Saya menggunakan gelandangan untuk pengembangan. Saya lupa mematikan beberapa VM. Ketika saya pergi untuk keluar dari mesin host saya, proses shutdown Ubuntu tampaknya hang.

Mungkinkah ada cara untuk menutup semua kotak gelandangan dengan sedikit commandline-fu? Sesuatu seperti yang berikut ini, tetapi sesuatu yang, yah, bekerja.

for f in $HOME/vagrant;
do;
  cd $f
  vagrant halt
done;
Rick
sumber
Saya tidak tahu gelandangan tetapi tampaknya terkait dengan VMWare, bukan VirtualBox. Apakah Anda benar-benar menggunakan VirtualBox?
terdon
@terdon: Vagrant hanya mendukung Vbox pada awalnya. Saya pikir mereka sekarang mendukung jenis format VM lainnya (mengerti VMWare)
Sylvain Pineau
@SylvainPineau ah, OK. Saya baru saja melihat halaman web mereka dan melihat tautan "VMWare Integration" dan berasumsi. Terimakasih atas klarifikasinya.
terdon
1
Saya akan melihat skrip ini . Posting blog lengkap ada di sini . Tidak diuji
Sylvain Pineau
Richard tolong jangan sunting jawaban dalam pertanyaan Anda. Anda bebas menjawab pertanyaan Anda sendiri dalam jawaban yang terpisah. Saya memang memberi Anda upvote untuk pertanyaan yang bagus.
don.joey

Jawaban:

91

Untuk kontrol skrip mesin Virtual Box, kami dapat menggunakan perintah VBoxManage :

  • Daftar mesin yang berjalan (mengembalikan nama dan UUID):

    VBoxManage list runningvms
    
  • Hentikan menjalankan VM dengan "hibernasi" mereka (direkomendasikan untuk menghindari kehilangan data)

    VBoxManage controlvm <name|uuid> savestate
    
  • Poweroff menjalankan VMs (tidak disarankan karena kami dapat kehilangan data di tamu)

    VBoxManage controlvm <name|uuid> poweroff
    
  • Gunakan ACPI dalam OS tamu yang sadar ACPI (lebih disukai daripada poweroffuntuk tamu yang ramah)

    VBoxManage controlvm <name|uuid> acpipowerbutton
    

Lihat juga: Cara mematikan OS Tamu di VirtualBox menggunakan baris perintah

Perbarui dari OP

Berdasarkan jawaban yang benar yang dipilih di bawah ini, saya telah menambahkan skrip bash ini " $HOME/bin/stop-vagrant.sh". Jadi sekarang saya memiliki sesuatu yang dapat dengan aman memulai penghentian semua VM gelandangan yang mungkin telah saya nyalakan namun terlupakan dalam suatu sesi.

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

Perintah Dijelaskan:

vboxmanage list runningvms | - Mendapat daftar semua vms yang berjalan di bawah VirtualBox

sed -r 's/.*\{(.*)\}/\1/' | - menghapus string ke nomor id

xargs -L1 -I {} VBoxManage controlvm {} savestate - Menjalankan perintah save state pada setiap kotak yang terbuka.

Di xargs

  • -L1 - ambil satu baris sekaligus
  • -I {} - menggunakan {} sebagai penampung untuk perintah selanjutnya
Takkat
sumber
Whoo Hoo! Dengan saran di atas, baris perintah ini berfungsi dengan baik: daftar vboxmanage runningvms | sed -r 's /.* \ {(. *) \} / \ 1 /' | xargs -L1 -I {} VBoxManage controlvm {} savestate
Rick
1
Catatan, -ropsi ini unik untuk GNU Sed.
George V. Reilly
Satu kalimat liner ajaib terbaik yang pernah kulihat! Kerja bagus! : D
tftd
1
Pada OSX / macOS, Anda harus menggunakan -Esebagai ganti -r. Ini adalah bendera untuk menggunakan ekspresi reguler yang diperluas.
JayD3e
22

Jawaban lainnya sangat bagus untuk menangani Virtualbox, tetapi Vagrant fitur mekanisme sendiri untuk menangani Mesin Virtual, dan seperti yang disebutkan dalam salah satu komentar, itu mendukung lebih dari sekedar VirtualBox, hanya VMWare saat ini, tetapi siapa yang tahu nanti!

Ini sepertinya bekerja untuk saya:

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

catatan:

Ini bekerja dengan versi Vagrant setelah 1.6, untuk versi yang lebih lama, Anda mungkin harus meningkatkan, tetapi jika Anda tidak bisa, salah satu opsi lain yang berfokus pada Virtualbox mungkin lebih baik.

ThomasRedstone
sumber
4
ini jelas jawaban yang jauh lebih benar (tm). @ Richard sebaiknya mempertimbangkan menerima yang ini sebagai gantinya
nhed
The global-statuskomando diperkenalkan di Vagrant 1,6 . Pengguna pada versi Vagrant yang lebih lama, terutama mereka yang telah menginstalnya melalui apt-getdan mungkin masih di 1.4.3, perlu memperbarui instalasi Vagrant mereka sebelum mereka dapat menggunakan perintah ini.
Curtis Gibby
1
BSD xargstidak mendukung -r, karena itu Anda dapat menginstal gxargsvia brewdan menggunakannya sebagai gantinya.
kenorb
11

Mekanisme saya untuk ini:

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

  • status global mencantumkan semua kotak
  • memfilter untuk baris yang mengandung virtualbox(Menyaring teks bantuan, akan rusak jika Anda menggunakan beberapa penyedia lain)
  • Saring yang hanya menampilkan 9 karakter pertama (ID unik global)
  • Meskipun kita masih bisa membaca baris dari input itu, bacalah sebagai variabel $ line lalu:
    • Cetak $ line itu
    • lari vagrant halt $linemenghentikan gelandangan untuk ID unik global itu

Ini lebih baik daripada metode Virtualbox di atas, karena itu akan menjalankan mekanisme shutdown yang dikonfigurasi gelandangan juga.

Aquarion
sumber
3
Perintah ini juga berfungsi untuk host OS X. Yang lain gagal karena perbedaan dalam argumen baris perintah yang menangani antara OSX dan versi Linux dari seddan awk. Terima kasih!
Andrew Андрей Листочкин
@ AndrewАндрейЛисточкин Konfirmasi - berfungsi dengan baik pada OS X 10. Tidak diuji pada OS lain.
setevoy
2
Perintah di atas mencoba untuk menghentikan semua kotak, tidak peduli apakah ada yang berjalan atau tidak, sehingga membutuhkan waktu lama untuk dieksekusi. Bagi saya, karena saya hanya menggunakan virtualbox, saya mengubah grep "virtualbox" menjadi "running", untuk mendapatkan yang berjalan saja.
Alex2php
Ini adalah jawaban yang bagus, tetapi Anda mungkin ingin menggunakan vagrant suspendalih-alih vagrant haltmenyimpan status dan menangguhkan untuk naik turun lebih cepat.
David Thomas
Benar, dan jika itu berhasil untuk Anda, itu hebat. Saya mengalami masalah ketepatan waktu yang besar dengan VM yang ditangguhkan di bawah Virtualbox, jadi saya tidak akan merekomendasikannya.
Aquarion
5

Dalam kasus orang lain sampai ke pertanyaan ini: Bagi mereka yang menggunakan VirtualBox, itu sudah dapat mengatasi ini, hanya melibatkan pengeditan file:

# 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

Sisi init.dbaiknya adalah tidak perlu mengedit / membuat logout atau stript untuk menjalankan perintah yang diposting dalam jawaban lain. Kelemahannya adalah solusi ini khusus untuk VirtualBox.

Diuji pada Ubuntu 14.10 dengan VirtualBox 4.3.18.

Semua kredit masuk ke pos ini .

Armando Pérez Marqués
sumber
5

Menggabungkan beberapa jawaban lain, ini akan menutup semua menjalankan kotak gelandangan virtualbox:

vagrant global-status | awk '/virtualbox running/{ print $1 }' | xargs vagrant halt
Ryan
sumber
Ini berhasil untuk saya!
Dayron Gallardo
3

Saya hanya menggunakan vagrant halt. Jika Anda menjalankannya tanpa argumen lebih lanjut, itu menghentikan semua mesin yang didefinisikan dalam Vagrantfile.

nomen
sumber
1

Jika Anda menulis skrip untuk mem-parsing perintah-perintah Vagrant, disarankan untuk mengurai output ramah-mesin ( --machine-readable) yang lebih konsisten.

Formatnya adalah:

timestamp,target,type,data...

jadi Anda dapat mengimpornya sebagai file CSV, karena dipisahkan oleh koma.

Dengan shell, mungkin lebih sulit untuk diurai, misalnya:

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

Lihat: Vagrant - Output yang dapat dibaca mesin


Namun saya merasa lebih mudah untuk mem-parsing output standar, misalnya

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

Btw. Secara teoritis vagrantperintah harus menerima ekspresi reguler untuk daftar VM yang ditangguhkan sesuai pos GH ini , misalnya:

vagrant suspend '*'

tetapi itu tidak bekerja dan ada bug # 7221 yang tertunda untuk memperbaikinya.


Tiket GitHub terkait:

kenorb
sumber
0

Ini mungkin atau mungkin tidak bekerja untuk Anda ;-) Bekerja untuk saya

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
taman brad
sumber