Tắt tất cả các máy ảo VirtualBox (vagrant) trong một lệnh bash dễ sử dụng (có thể được đưa vào tệp bash)


70

Tôi sử dụng vagrant để phát triển. Tôi quên tắt một vài máy ảo. Khi tôi đăng xuất khỏi máy chủ của mình, quá trình tắt máy Ubuntu dường như bị treo.

Có thể có một cách để kịch bản đóng tất cả các hộp mơ hồ với một chút dòng lệnh-fu? Một cái gì đó như sau, nhưng một cái gì đó, tốt, hoạt động.

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

Tôi không biết mơ hồ nhưng dường như nó được liên kết với VMWare chứ không phải VirtualBox. Bạn đang thực sự sử dụng VirtualBox?
terdon

@terdon: Vagrant chỉ hỗ trợ Vbox ban đầu. Tôi nghĩ rằng họ hiện hỗ trợ các loại định dạng VM khác (hiểu VMWare)
Sylvain Pineau

@SylvainPineau ah, OK. Tôi vừa xem nhanh trang web của họ và thấy một liên kết "tích hợp VMWare" và được giả định. Cảm ơn bạn đã làm rõ.
terdon

1
Tôi sẽ xem kịch bản này . Bài viết đầy đủ trên blog là ở đây . Chưa được thử nghiệm
Sylvain Pineau

Richard xin đừng chỉnh sửa câu trả lời trong câu hỏi của bạn. Bạn được tự do trả lời câu hỏi của riêng bạn trong một câu trả lời riêng biệt. Tôi đã cung cấp cho bạn một upvote cho một câu hỏi hay.
don.joey

Câu trả lời:


91

Để kiểm soát tập lệnh của các máy Virtual Box, chúng tôi có thể sử dụng các lệnh VBoxManage :

  • Liệt kê các máy đang chạy (trả về tên và UUID):

    VBoxManage list runningvms
    
  • Dừng chạy VM bằng cách "ngủ đông" chúng (được đề xuất lại để tránh mất dữ liệu)

    VBoxManage controlvm <name|uuid> savestate
    
  • Máy ảo chạy Poweroff (không được khuyến nghị vì chúng tôi có thể mất dữ liệu trong máy khách)

    VBoxManage controlvm <name|uuid> poweroff
    
  • Sử dụng ACPI trong hệ điều hành khách nhận biết ACPI (thích hợp hơn để powerofftắt máy khách một cách duyên dáng)

    VBoxManage controlvm <name|uuid> acpipowerbutton
    

Xem thêm: Cách tắt hệ điều hành Guest trong VirtualBox một cách an toàn bằng dòng lệnh

Cập nhật từ OP

Dựa trên câu trả lời đúng được chọn này bên dưới, tôi đã thêm tập lệnh bash này " $HOME/bin/stop-vagrant.sh". Vì vậy, bây giờ tôi có một cái gì đó có thể bắt đầu một cách an toàn tất cả các máy ảo mơ hồ mà tôi có thể đã bật mà chưa quên trong một phiên.

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

Lệnh giải thích:

vboxmanage list runningvms | - nhận danh sách tất cả các vms đang chạy trong VirtualBox

sed -r 's/.*\{(.*)\}/\1/' | - tước chuỗi xuống số id

xargs -L1 -I {} VBoxManage controlvm {} savestate - chạy lệnh lưu trạng thái trên mỗi hộp đang mở.

Trên, bật xargs

  • -L1 - thực hiện một dòng tại một thời điểm
  • -I {} - sử dụng {} làm chủ sở hữu vị trí cho lệnh tiếp theo

Ôi Hoo! Đưa ra lời khuyên ở trên, dòng lệnh này hoạt động kỳ diệu: danh sách vboxmanage runningvms | sed -r 's /.* \ {(. *) \} / \ 1 /' | xargs -L1 -I {} VBoxManage controlvm {} savestate
Rick

1
Lưu ý, -rtùy chọn này là duy nhất cho GNU Sed.
George V. Reilly

Một lớp lót ma thuật tốt nhất tôi từng thấy trong một thời gian! Làm tốt lắm! : D
tftd

1
Trên OSX / macOS, bạn sẽ cần sử dụng -Ethay vì -r. Đó là cờ để sử dụng các biểu thức chính quy mở rộng.
JayD3e

22

Câu trả lời khác là rất tốt để xử lý Virtualbox, nhưng Vagrant có các cơ chế riêng để xử lý các máy ảo và như đã đề cập trong một trong các ý kiến, nó hỗ trợ nhiều hơn là VirtualBox, chỉ VMWare vào lúc này, nhưng ai biết sau!

Điều này dường như làm việc cho tôi:

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

Ghi chú:

Điều này hoạt động với các phiên bản Vagrant sau 1.6, đối với các phiên bản cũ hơn, có lẽ bạn nên nâng cấp, nhưng nếu bạn không thể, một trong những tùy chọn khác tập trung vào Virtualbox có thể tốt hơn.


4
đây rõ ràng là một câu trả lời đúng (tm) hơn nhiều. @Richard nên xem xét chấp nhận cái này thay vào đó
nhed 23/12/14

Các global-statuslệnh đã được giới thiệu trong Vagrant 1.6 . Người dùng trên các phiên bản cũ hơn của Vagrant, đặc biệt là những người đã cài đặt nó qua apt-getvà có thể vẫn ở phiên bản 1.4.3, sẽ cần cập nhật cài đặt Vagrant trước khi họ có thể sử dụng lệnh này.
Curtis Gibby

1
BSD xargskhông hỗ trợ -r, do đó bạn có thể cài đặt gxargsqua brewvà sử dụng nó thay thế.
kenorb

11

Cơ chế của tôi cho việc này:

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

  • danh sách toàn cầu liệt kê tất cả các hộp
  • bộ lọc cho các dòng chứa virtualbox(Lọc văn bản trợ giúp, sẽ bị hỏng nếu bạn đang sử dụng một số nhà cung cấp khác)
  • Lọc để chỉ hiển thị 9 ký tự đầu tiên (ID duy nhất toàn cầu)
  • Mặc dù chúng ta vẫn có thể đọc một dòng từ đầu vào đó, nhưng hãy đọc nó dưới dạng biến $ line sau đó:
    • In ra dòng $ đó
    • chạy vagrant halt $linetạm dừng người lang thang cho ID duy nhất toàn cầu đó

Điều này tốt hơn phương pháp Virtualbox ở trên, vì nó cũng sẽ chạy bất kỳ cơ chế tắt được cấu hình mơ hồ nào.


3
Lệnh này cũng hoạt động cho máy chủ OS X. Những người khác không thành công do sự khác biệt trong xử lý đối số dòng lệnh giữa các phiên bản OSX và Linux sedawk. Cảm ơn!
Andrew Андрей Листочкин

@ Andrew ngã sau khi xác nhận - hoạt động tốt trên OS X 10. Không được thử nghiệm trên hệ điều hành khác mặc dù.
setevoy

2
Lệnh trên cố gắng tạm dừng tất cả các hộp, bất kể có chạy hay không, do đó mất nhiều thời gian để thực thi. Đối với tôi, vì tôi chỉ sử dụng hộp ảo, tôi đã thay đổi grep "hộp ảo" thành "đang chạy", để chỉ lấy những cái đang chạy.
Alex2php

Đây là một câu trả lời tốt, nhưng bạn có thể muốn sử dụng vagrant suspendthay vì vagrant haltđể lưu trạng thái và tạm dừng để nhanh hơn và lên.
David Thomas

Đúng, và nếu nó làm việc cho bạn thì thật tuyệt. Tôi đã gặp vấn đề lớn về thời gian với các máy ảo bị treo trong Virtualbox, vì vậy tôi không khuyên dùng nó.
Aquarion

5

Trong trường hợp người khác gặp phải câu hỏi này: Đối với những người sử dụng VirtualBox, việc này có thể giải quyết vấn đề này, chỉ liên quan đến việc chỉnh sửa một tệp:

# 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

Ưu điểm là không cần thiết phải chỉnh sửa / tạo bất kỳ đăng xuất hoặc thoát init.dy để chạy các lệnh được đăng trong các câu trả lời khác. Nhược điểm là giải pháp này dành riêng cho VirtualBox.

Đã thử nghiệm trên Ubuntu 14.10 với VirtualBox 4.3.18.

Tất cả tín dụng đi đến bài này .


5

Kết hợp một số câu trả lời khác, điều này sẽ đóng tất cả các hộp ảo của hộp ảo đang chạy:

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

Điều này làm việc cho tôi!
Dayron Gallardo

3

Tôi chỉ sử dụng vagrant halt. Nếu bạn chạy nó mà không có đối số tiếp theo, nó sẽ dừng tất cả các máy được xác định trong Vagrantfile.


1

Nếu bạn đang viết tập lệnh để phân tích các lệnh Vagrant, bạn nên phân tích đầu ra thân thiện với máy ( --machine-readable) phù hợp hơn.

Định dạng là:

timestamp,target,type,data...

để bạn có thể nhập tệp dưới dạng tệp CSV, vì nó được phân tách bằng dấu phẩy.

Với shell, có lẽ khó phân tích hơn, ví dụ:

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

Xem: Vagrant - Đầu ra máy có thể đọc được


Tuy nhiên tôi thấy phân tích đầu ra tiêu chuẩn dễ dàng hơn, vd

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

Btw. vagrantLệnh về mặt lý thuyết nên chấp nhận một biểu thức chính quy cho danh sách các VM tạm ngưng theo bài viết GH này , ví dụ:

vagrant suspend '*'

nhưng nó không hoạt động và có một lỗi # 7221 đang chờ xử lý để sửa nó.


Vé GitHub liên quan:


0

Điều này có thể hoặc không thể làm việc cho bạn ;-) Làm việc cho tôi

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.