在使用Virtualbox并尝试在VM(Windows guest虚拟机)内执行命令时,我注意到随机超时正在发生。我编写了一个简单的脚本来进一步调查该问题(请参阅文章结尾)。
我发出的呼叫中有1-2%发生超时(即使增加下面脚本片段中给出的超时也是如此)。可以肯定地说,这些调用实际上确实在客户机系统上执行。它们简单地似乎在执行后卡住了。
基本通话如下:
vboxmanage guestcontrol w10 run --exe C:\\Windows\\System32\\cmd.exe --timeout 10000 --username bar --password foo --wait-stdout -- cmd.exe /c echo hi
我的目标是将随机超时减少到0%。
虽然我在玩不同的参数时注意到,但如果我将--wait-stdout
更改为--no-wait-stdout
,超时就消失了。
official documentation解释了该开关:
不要等到来宾进程结束并收到其退出代码和原因/标志
,
添加此命令将导致零超时,但不能保证命令输出可用。
我注意到在运行失败的命令时检查vboxmanage guestcontrol的返回码(例如cd foobar
,假设文件夹foobar不存在),我注意到,对于失败的命令,返回码为非零。
然后我尝试使用PowerShell而不是cmd。基本的PowerShell版本如下所示:
vboxmanage guestcontrol w10 run --exe C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe --timeout 10000 --username bar --password foo --wait-stdout -- powershell.exe -InputFormat none -NoLogo -NonInteractive -NoProfile -Command echo hi
请注意,-InputFormat none
开关是PowerShell的未真正记录的命令行开关。不使用它会产生更糟糕的结果(由于错误,很可能会发生100%的超时)。 Source.
使用PowerShell产生的总体结果要比cmd稍差(2%的调用随机超时)。
--no-wait-stdout
开关时,我是否可以假设即发即弃逻辑,还是会一直始终得到有意义的返回代码?我在主机系统上运行vbox 5.2.34_Ubuntur133883。 Windows客户端(10.0.18362)上的来宾添加5.2.34。
测试脚本段:
#!/bin/bash
readonly ITERATIONS=1000
fail_counter=0
for i in $(seq 1 $ITERATIONS) ; do
if ! vboxmanage guestcontrol w10 run --exe C:\\Windows\\System32\\cmd.exe --timeout 10000 --username bar --password foo --wait-stdout -- cmd.exe /c echo hi > /dev/null 2>&1; then
((++fail_counter))
fi
done
echo "timeouts: $fail_counter"