ปิด VirtualBox ทั้งหมด (คนจรจัด) VMs ในหนึ่งคำสั่ง bash ที่ใช้งานง่าย (ซึ่งสามารถใส่ลงในไฟล์ bash)


70

ฉันใช้คนเร่ร่อนในการพัฒนา ฉันลืมปิด VM บางตัว เมื่อฉันออกจากระบบเครื่องโฮสต์กระบวนการปิดเครื่องของ Ubuntu จะหยุดทำงาน

อาจมีวิธีการสคริปต์ปิดกล่องคนจรจัดทั้งหมดด้วย bit commandline-fu? บางอย่างเช่นสิ่งต่อไปนี้ แต่เป็นสิ่งที่ใช้ได้ผล

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

ฉันไม่รู้จักคนจรจัด แต่ดูเหมือนว่าจะเชื่อมโยงกับ VMWare ไม่ใช่ VirtualBox คุณใช้ VirtualBox จริงหรือ
terdon

@terdon: Vagrant รองรับเฉพาะ Vbox ในตอนแรก ฉันคิดว่าตอนนี้พวกเขาสนับสนุนรูปแบบ VM ประเภทอื่น ๆ (เข้าใจ VMWare)
Sylvain Pineau

@SylvainPineau ah, OK ฉันเพิ่งดูหน้าเว็บของพวกเขาอย่างรวดเร็วและเห็นลิงก์ "VMWare Integration" และสันนิษฐานว่า ขอขอบคุณสำหรับการชี้แจง.
terdon

1
ฉันจะดูสคริปต์นี้ โพสต์บล็อกเต็มรูปแบบที่นี่ ไม่ผ่านการทดสอบ
Sylvain Pineau

ริชาร์ดโปรดอย่าแก้ไขคำตอบในคำถามของคุณ คุณมีอิสระที่จะตอบคำถามของคุณเองในคำตอบแยกต่างหาก ฉันให้คะแนนโหวตสำหรับคำถามที่ดี
don.joey

คำตอบ:


91

สำหรับการควบคุมสคริปต์เครื่องเสมือนกล่องสคริปต์เราสามารถใช้ประโยชน์จากคำสั่งVBoxManage :

  • แสดงรายการเครื่องที่ใช้งาน (ชื่อที่ส่งคืนและ UUID):

    VBoxManage list runningvms
    
  • หยุดการเรียกใช้ VM โดย "จำศีล" พวกเขา (แนะนำใหม่เพื่อหลีกเลี่ยงการสูญเสียข้อมูล)

    VBoxManage controlvm <name|uuid> savestate
    
  • Poweroff ใช้งาน VM (ไม่แนะนำเพราะเราอาจสูญเสียข้อมูลในแขก)

    VBoxManage controlvm <name|uuid> poweroff
    
  • ใช้ ACPI ในระบบปฏิบัติการแขก ACPI ที่รับรู้ (เหมาะpoweroffสำหรับการปิดระบบของผู้เยี่ยมชมอย่างสง่างาม)

    VBoxManage controlvm <name|uuid> acpipowerbutton
    

โปรดดูเพิ่มเติมที่: วิธีปิดระบบปฏิบัติการ Guest อย่างปลอดภัยใน VirtualBox โดยใช้บรรทัดคำสั่ง

อัปเดตจาก OP

จากคำตอบที่ถูกต้องที่เลือกไว้ด้านล่างนี้ฉันได้เพิ่ม bash script " $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/' | - ดึงสตริงลงไปที่หมายเลข id

xargs -L1 -I {} VBoxManage controlvm {} savestate - เรียกใช้คำสั่งบันทึกสถานะในแต่ละกล่องที่เปิดอยู่

บน xargs

  • -L1 - ใช้ทีละบรรทัด
  • -I {} - ใช้ {} เป็นตัวยึดตำแหน่งสำหรับคำสั่งถัดไป

Whoo Hoo! ด้วยคำแนะนำข้างต้นบรรทัดคำสั่งนี้ใช้งานได้ดี: vboxmanage list runningvms | sed -r 's /.* \ {(. *) \} / \ 1 /' | xargs -L1 -I {} VBoxManage controlvm {} savestate
Rick

1
หมายเหตุ-rตัวเลือกนั้นไม่ซ้ำกับ GNU Sed
George V. Reilly

สุดยอดเวทมนต์อันหนึ่งที่ฉันเคยเห็นมาซักพัก! เยี่ยมมาก! : D
tftd

1
ใน OSX / MacOS คุณจะต้องใช้แทน-E -rมันเป็นธงสำหรับการใช้การแสดงออกปกติเพิ่มเติม
JayD3e

22

คำตอบอื่น ๆ นั้นยอดเยี่ยมสำหรับการจัดการ Virtualbox แต่ Vagrant มีกลไกของตัวเองสำหรับการจัดการ Virtual Machines และดังที่ได้กล่าวไว้ในหนึ่งในความคิดเห็นมันสนับสนุนมากกว่า VirtualBox เพียง VMWare ในตอนนี้ แต่ใครจะรู้ในภายหลัง!

ดูเหมือนว่าจะใช้งานได้สำหรับฉัน:

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

บันทึก:

สิ่งนี้ใช้ได้กับเวอร์ชัน Vagrant หลังจาก 1.6 สำหรับเวอร์ชันเก่าคุณควรอัปเกรด แต่ถ้าคุณทำไม่ได้หนึ่งในตัวเลือกอื่น ๆ ที่มุ่งเน้นไปที่ Virtualbox อาจดีกว่า


4
เห็นได้ชัดว่านี่เป็นคำตอบที่ถูกต้องมาก (tm) @ Richard ควรพิจารณายอมรับคนนี้แทน
nhed

global-statusคำสั่งที่ถูกนำมาใช้ในจรจัด 1.6 ผู้ใช้ในเวอร์ชันเก่าของ Vagrant โดยเฉพาะผู้ที่ติดตั้งผ่านทางapt-getและอาจยังอยู่ใน 1.4.3 จะต้องอัปเดตการติดตั้ง Vagrant ก่อนจึงจะสามารถใช้คำสั่งนี้ได้
Curtis Gibby

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;

  • global-status แสดงรายการกล่องทั้งหมด
  • ตัวกรองสำหรับบรรทัดที่มีvirtualbox(กรองข้อความช่วยเหลือจะแตกหากคุณใช้ผู้ให้บริการรายอื่น)
  • กรองเพื่อแสดงเฉพาะอักขระ 9 ตัวแรก (รหัสที่ไม่ซ้ำกันทั่วโลก)
  • ในขณะที่เรายังคงสามารถอ่านบรรทัดจากอินพุตนั้นให้อ่านมันเป็นตัวแปร $ line แล้ว:
    • พิมพ์ที่บรรทัด $
    • เรียกใช้การvagrant halt $lineหยุดคนจรจัดสำหรับ ID เฉพาะทั่วโลกนั้น

นี่เป็นวิธีที่ดีกว่าวิธี Virtualbox ข้างต้นเพราะมันจะเรียกใช้กลไกการปิดระบบที่กำหนดค่าคนจรจัดด้วย


3
คำสั่งนี้ใช้ได้กับโฮสต์ OS X เช่นกัน อื่น ๆ ล้มเหลวเนื่องจากความแตกต่างในการขัดแย้งบรรทัดคำสั่งจัดการระหว่าง OSX และรุ่นลินุกซ์และsed awkขอบคุณ!
Andrew АндрейЛисточкин

@ AndrewАндрейЛисточкинยืนยัน - ทำงานบน OS X 10 ได้ดี ไม่ได้ทดสอบกับระบบปฏิบัติการอื่นแม้ว่า
setevoy

2
คำสั่งดังกล่าวพยายามที่จะหยุดกล่องทั้งหมดไม่ว่าจะมีการเรียกใช้หรือไม่จึงใช้เวลานานในการดำเนินการ สำหรับฉันเนื่องจากฉันใช้ virtualbox เท่านั้นฉันเปลี่ยน grep "virtualbox" เป็น "running" เพื่อรับเฉพาะส่วนที่กำลังรันอยู่
Alex2php

นี่เป็นคำตอบที่ดี แต่คุณอาจต้องการใช้vagrant suspendแทนvagrant haltการบันทึกสถานะและหยุดพักเพื่อให้เร็วขึ้น
David Thomas

จริงและถ้าได้ผลกับคุณมันยอดเยี่ยมมาก ฉันมีปัญหาเกี่ยวกับจับเวลาจำนวนมากเกี่ยวกับ VM ที่ถูกระงับภายใต้ Virtualbox ดังนั้นฉันจะไม่แนะนำ
Aquarion

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

ข้อดีคือไม่จำเป็นต้องแก้ไข / สร้าง logout หรือinit.dstript ใด ๆเพื่อรันคำสั่งที่โพสต์ในคำตอบอื่น ๆ ข้อเสียคือโซลูชันนี้มีเฉพาะกับ VirtualBox

ทดสอบบน Ubuntu 14.10 ด้วย VirtualBox 4.3.18

เครดิตทั้งหมดไปที่โพสต์นี้


5

เมื่อรวมคำตอบอื่น ๆ เข้าด้วยกันนี่จะเป็นการปิดกล่องผู้ใช้เสมือนจริงทั้งหมด:

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

สิ่งนี้ได้ผลสำหรับฉัน!
Dayron Gallardo

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คำสั่งควรยอมรับการแสดงออกปกติสำหรับรายการของ VMs ที่จะระงับตามโพสต์ 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.