Shell 如何等到VirtualBox完成加载后在Windows批处理中执行下一个命令?

Shell 如何等到VirtualBox完成加载后在Windows批处理中执行下一个命令?,shell,command-line,batch-file,virtualbox,wait,Shell,Command Line,Batch File,Virtualbox,Wait,我最近写的CMD批处理文件有点问题。这是为了在工作中启动我的开发环境,在大多数情况下,它是有效的: @echo off start cmd.exe start notepad++.exe start sublime_text.exe start outlook.exe start communicator.exe start "* Starting VirtualBox ..." virtualbox.exe start sh.exe start firefox.exe 我面临的挑战是,我想启

我最近写的CMD批处理文件有点问题。这是为了在工作中启动我的开发环境,在大多数情况下,它是有效的:

@echo off
start cmd.exe
start notepad++.exe
start sublime_text.exe
start outlook.exe
start communicator.exe
start "* Starting VirtualBox ..." virtualbox.exe
start sh.exe
start firefox.exe
我面临的挑战是,我想启动git bash(sh.exe),但在公司配置中,virtualbox必须为vagrant(一个基于shell的virtualbox管理器)启动并运行,才能正确加载。因此,由于这种依赖关系,我需要virtualbox.exe在启动git bash shell(sh.exe)之前启动并完全完成加载(我们不需要“启动”和框)

我已经找过了,但还不知道怎么做。我不断得到结果,建议:

  • /等等
  • ping localhost(n)次以创建计时器破解
这些选项的问题是/wait在VirtualBox关闭之前不会移动到下一个命令——这不是我想要的。第二种选择是基于时间的等待,这也不能解决我在这种情况下的问题


我做错了什么?

正如您所观察到的,一旦虚拟机实际打开,VirtualBox/VBoxManage进程将返回并退出。没有一种好的方法可以在一开始就连接到guest,不过您可以做的一件事是指示VirtualBox运行命令并检查退出代码。我会在启动来宾VM之后,但在您想要启动
sh.exe
之前,将此代码插入批处理文件脚本中:

:CheckVBox
VBoxManage guestcontrol Win8 exec --image c:\Windows\System32\ipconfig.exe --wait-exit --username Goyuix --password VirtualBoxRox
IF NOT ERRORLEVEL 0 (
  REM Do something to sleep here, pinging localhost or timeout
  GOTO CheckVBox
)
REM VM Ready, go ahead and fire up other apps that depend on it
注意:您需要在path环境变量中设置
VBoxManage
可执行文件的路径。在Windows上,它通常是:C:\Program Files\Oracle\VirtualBox

诚然,您可能需要一些更健壮的东西,只需运行
ipconfig
即可检测VM是否真的准备就绪。我不确定什么服务等。您将取决于是否有可用的服务,但这可能足以让您渡过难关,并且肯定可以调整为检查服务状态等。

实现这一点的“最佳”方法是在主机上使用VBoxManage,在来宾机上使用属性结合使用VBoxControl

这种方式是主机等待属性设置,当你认为机器有“加载”时,客户机将设置这个属性。对我来说,我只是从登录脚本设置属性

因此,在我的Linux主机上,我说:

VBoxManage guestproperty wait My_Virtual_Machine_Name Wait_For_Logon_Event
这将永远等待/阻止,如果您愿意,可以添加超时

然后在登录脚本或机器启动脚本中的Windows来宾上执行:

VBoxControl guestproperty set Wait_For_Logon_Event Event_Now_Set
这将导致在主机端继续执行:

Name: Wait_For_Logon_Event, value: Event_Now_Set, flags:

哇!谢谢paulm的灵感

发现了一个很好的机会

我正在使用以下命令浏览build it guest OS属性:

 VBoxControl guestproperty enumerate -patterns *
我发现了一个很好的属性“/VirtualBox/GuestInfo/OS/LoggedInUsers

在来宾操作系统引导期间,此属性从“No value set!”通过值“0”更改为“1”(如果用户自动登录)。 在Windows和linux上都可以正常工作

>VBoxManage guestproperty get "WIN7_32" "/VirtualBox/GuestInfo/OS/LoggedInUsers"
No value set!

>VBoxManage guestproperty get "WIN7_32" "/VirtualBox/GuestInfo/OS/LoggedInUsers"
Value: 0

>VBoxManage guestproperty get "WIN7_32" "/VirtualBox/GuestInfo/OS/LoggedInUsers"
Value: 1
因此,您无需添加任何内容即可在来宾操作系统上启动!好极了

您甚至可以使用等待

VBoxManage guestproperty wait "WIN7_32" "/VirtualBox/GuestInfo/OS/LoggedInUsers"

但请记住,当来宾操作系统到达欢迎屏幕时,此命令将返回0,不过,
get
确实起作用。用户似乎不再使用
wait
(VirtualBox 5.2.22)。所以我换了另一个地方:

VBoxManage guestproperty wait <host> "/VirtualBox/GuestInfo/OS/NoLoggedInUsers"

其中
应为正在运行的。然后将该列表与未运行计算机的列表进行比较。

为什么不ping虚拟主机直到其响应?我想,因为虚拟机可能没有启用网络,请参阅我的属性解决方案以获得更可靠的方法:)谢谢@Goyuix。我在哪里输入这些东西?某种配置文件?命令行?不客气!这是一个很好的问题。我已经更新了原始答案,以便更清楚地表明您应该将代码添加到现有的批处理脚本中。如果这解决了你的问题,我将感谢你的支持和接受的答案。谢谢你的建议!不幸的是,我已经离开了那个合同,所以我将无法测试它。但是,也许这些信息将来会有用。我认为,使用属性而不是在循环中运行程序是更好的方法。在“GUESTroperty set”中找到打印错误大约需要2分钟,但现在可以正常工作了!谢谢。似乎“LoggedInUsers”不再可用(5.2.22)
VBoxManage GuestProperty Enumerate
显示了一个同样可用的属性:
NoLoggedInUsers
,这是一个布尔值,但由于我们只等待它变为可用,所以在这里这并不重要。“LoggedInUsers”可用,但出于某种原因(bug?)您不能等待它。不过,你可以“得到”它。
vboxmanage guestproperty enumerate <host> | grep GuestInfo/OS