在一个易于使用的bash命令(可以将其放入bash文件中)中关闭所有VirtualBox(无用)VM。


70

我用无业游民的发展。我忘了关闭一些虚拟机。当我退出主机时,Ubuntu关闭进程似乎挂起。

可能有一种方法可以用一些命令行赋来关闭所有无聊的盒子吗?类似于以下内容,但可以正常工作。

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

我不知道流浪汉,但它似乎链接到VMWare,而不是VirtualBox。您实际上在使用VirtualBox吗?
terdon

@terdon:流浪汉最初仅支持Vbox。我认为他们现在支持其他类型的VM格式(了解VMWare)
Sylvain Pineau

@SylvainPineau啊,好的。我只是快速浏览了他们的网页,并看到了“ VMWare集成”链接并假设了。感谢您的澄清。
terdon

1
我看一下这个脚本。完整的博客文章在这里。未测试
西尔万·皮诺

理查德,请不要编辑您问题的答案。您可以自由在单独的答案中回答自己的问题。我确实给你一个很好的问题的支持。
don.joey 2014年

Answers:


91

为了对Virtual Box计算机进行脚本化控制,我们可以使用VBoxManage命令:

  • 列出正在运行的计算机(返回名称和UUID):

    VBoxManage list runningvms
    
  • 通过“休眠”虚拟机来停止运行(建议避免丢失数据)

    VBoxManage controlvm <name|uuid> savestate
    
  • 关闭正在运行的VM的电源(不建议这样做,因为我们可能会丢失来宾中的数据)

    VBoxManage controlvm <name|uuid> poweroff
    
  • 在支持ACPI的来宾操作系统中使用ACPI(最好poweroff是正常关闭来宾)

    VBoxManage controlvm <name|uuid> acpipowerbutton
    

另请参阅:如何使用命令行安全关闭VirtualBox中的Guest OS

从OP更新

根据下面选择的正确答案,我添加了bash脚本“ $HOME/bin/stop-vagrant.sh”。因此,现在我有了一些可以安全地停止所有闲置虚拟机的功能,这些虚拟机我可能已经打开但在会话中忘记了。

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

命令说明:

vboxmanage list runningvms | -获取VirtualBox下所有正在运行的虚拟机的列表

sed -r 's/.*\{(.*)\}/\1/' | -将字符串剥离为ID号

xargs -L1 -I {} VBoxManage controlvm {} savestate -在打开的每个框上运行save state命令。

xargs

  • -L1 -一次乘一行
  • -I {} -使用{}作为下一个命令的占位符

呜呼!根据以上建议,此命令行可以正常运行:vboxmanage list runningvms | sed -r's /.* \ {(。*)\} / \ 1 /'| xargs -L1 -I {} VBoxManage controlvm {} savestate
Rick

1
注意,该-r选项对于GNU Sed是唯一的。
乔治五世·赖利

我已经见过的最好的神奇单线纸了!做得好!:D
tftd

1
在OSX / macOS上,您需要使用-E而不是-r。这是使用扩展正则表达式的标志。
JayD3e

22

另一个答案对处理Virtualbox很有帮助,但是Vagrant具有自己的处理虚拟机的机制,正如其中一条评论中提到的那样,它不仅仅支持VirtualBox,现在还支持VMWare,但后来知道!

这似乎为我工作:

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

注意:

这适用于1.6以后的Vagrant版本,对于较旧的版本,您应该升级,但如果不能升级,则专注于Virtualbox的其他选项之一可能会更好。


4
这显然是一个更正确的答案。@Richard应该考虑改为接受这一点
nhed 2014年

global-status命令在Vagrant 1.6引入。使用旧版本Vagrant的用户,尤其是通过Vagrant安装apt-get并可能仍在1.4.3上的用户,需要先更新其Vagrant安装,然后才能使用此命令。
Curtis Gibby 2015年

1
BSD xargs不支持-r,因此您可以gxargs通过安装brew并使用它。
kenorb '16

11

我的机制是:

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

  • 全局状态列出所有框
  • 过滤包含以下内容的行virtualbox(过滤掉帮助文本,如果使用其他提供程序,则将中断)
  • 进行过滤以仅显示前9个字符(全局唯一ID)
  • 虽然我们仍然可以从该输入读取一行,但是将其读取为变量$ line,然后:
    • 打印出该$ line
    • 运行vagrant halt $line停止流浪的全球唯一的ID

这比上面的Virtualbox方法更好,因为它也会运行任何由vagrant配置的关机机制。


3
此命令也适用于OS X主机。其他失败的原因是OSX和Linux版本的sed和之间在命令行参数处理方面存在差异awk。谢谢!
安德鲁АндрейЛисточкин16年

@AndrewАндрейЛисточкин确认-适用于OS X 10。尽管未在其他操作系统上进行测试。
setevoy '16

2
上面的命令试图暂停所有盒子,无论是否正在运行,都需要很长时间才能执行。对我来说,因为我只使用virtualbox,所以我将“ virtualbox” grep更改为“ running”,以仅获取正在运行的。
Alex2php '16

这是一个很好的答案,但是您可能想使用vagrant suspend而不是vagrant halt保存状态并暂停以更快地上下移动。
大卫·托马斯

是的,如果对您有用,那就太好了。我在Virtualbox下挂起的VM遇到大量的计时问题,因此不推荐使用。
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

这样做的好处是不必编辑/创建任何注销或init.d分段来运行其他答案中发布的命令。缺点是该解决方案特定于VirtualBox。

在Ubuntu 14.10上使用VirtualBox 4.3.18进行了测试。

所有的功劳都归这个职位


5

结合其他一些答案,这将关闭所有正在运行的virtualbox vagrant box:

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文件。

使用shell,可能更难解析,例如:

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

请参阅:无业游民-机器可读的输出


但是我发现更容易解析标准输出,例如

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

顺便说一句。理论上,该vagrant命令应根据此GH post接受要挂起的VM列表的正则表达式,例如:

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.