Answers:
如果使用sudo reboot
程序,则将发出终止信号,自动终止程序,而不会给应用程序时间来处理这种情况。这不是错误,它始终以相同的方式工作,这是预期的行为。
还有一个类似的问题在这里你可以看到哪些命令给出当你按下shutdown
,reboot
,suspend
,用户菜单等按键,这样的解决方案应该问你们是不是要关闭一个窗口与正在运行的应用程序,它最好的时候做什么(在您的情况)sudo shutdown
。看一看
我建议使用更复杂的方法,包括新手作业,启动和停止脚本。例如,我使用的是Windows XP,因为我的主目录允许使用tombert ...,您应该进行相应的更改。它的优点是无论您做什么(重新启动,关闭,按下电源按钮),都能很好地处理您的虚拟机。
首先,将新贵作业放入/etc/init/winxpvm.conf中:
description "WinXP VirtualBox job"
author "Thomas Perschak"
## 0: system halt
## 1: single-user mode
## 2: graphical multi-user plus networking
## 6: system reboot
start on started rc RUNLEVEL=[2]
stop on starting rc RUNLEVEL=[!2]
## upstart config
kill timeout 120
kill signal SIGCONT
nice -10
## start WinXP VirtualBox
exec /home/tombert/scripts/winxpvm-start.sh
## stop WinXP VirtualBox
pre-stop exec /home/tombert/scripts/winxpvm-stop.sh
upstart作业在运行级别2(处于图形模式)下启动虚拟机,在本例中,它使用来提高优先级nice
。为了很好地关闭虚拟机,我需要使用该kill signal SIGCONT
语句“禁用”暴发户终止。这样一来,虚拟机将首先运行(避免使用默认值SIGTERM
)。120秒后,SIGKILL
无论如何都会发送。相反,我正在运行winxpvm-stop.sh
脚本。
旁注1:节start on started runlevel [2]
和stop on starting runlevel [!2]
不起作用。必须特别提到这项工作rc
。
旁注2:新手手册也有什么令人困惑的地方:kill signal
节指定5秒钟后发送的信号。在此示例中,我将其设置为SIGTERM
(默认)为SIGCONT-但是5秒钟的超时时间我无法更改。该kill timeout
节指定SIGKILL
发送之前的超时-该信号不能更改。因此,一种改进是定义新的节term signal
和term timeout
。
这是启动脚本winxpvm-start.sh:
#! /bin/bash -e
function dostart()
{
echo -n "Running WinXP ... "
vboxheadless --startvm WinXP
echo "now closed"
}
export -f dostart
if [ $(whoami) != "tombert" ]; then
su -c dostart tombert
else
dostart
fi
因为所有设置等都是在用户模式下完成的(因为我的登录名是tombert),所以即使以root身份运行,我也要将帐户更改为tombert。当然,可以在upstart配置中更改用户,但是该解决方案使我可以选择从控制台“手动”启动/停止虚拟机。
更有趣的是winxpvm-stop.sh中的关闭脚本:
#! /bin/bash
function dostop()
{
## check if WinXP is running
vboxmanage showvminfo WinXP --machinereadable | grep -q 'VMState="running"' &> /dev/null
if [ $? -ne 0 ]; then
echo "WinXP not running"
exit
fi
## try gracefully shutdown
echo -n "Shutting down WinXP ... "
#vboxmanage controlvm WinXP acpipowerbutton
vboxmanage guestcontrol WinXP execute --image "%SystemRoot%\system32\shutdown.exe" --username tombert --password <mypassword> --wait-exit -- "-s" "-f" "-t" "0" &> /dev/null
## check vm status
INDEX=60
while [ $INDEX -gt 0 ]; do
echo -n "$INDEX "
vboxmanage showvminfo WinXP --machinereadable | grep -q 'VMState="running"' &> /dev/null
if [ $? -ne 0 ]; then
echo "gracefully done"
break
fi
sleep 1
let INDEX+=-1
done
## close forcefully
if [ $INDEX -eq 0 ]; then
vboxmanage controlvm WinXP poweroff &> /dev/null
echo "forcefully done"
fi
}
export -f dostop
if [ $(whoami) != "tombert" ]; then
su -c dostop tombert
else
dostop
fi
首先,我与启动脚本中的操作相同-我将用户从root更改为我的帐户tombert。现在让我们看一下函数dostop
。首先,我正在检查虚拟机是否正在运行。然后,我尝试通过使用发送直接关闭消息到WinXP来“软”关闭guestcontrol
。在这里,您必须提供WinXP帐户的凭据,在我的情况下,该凭据是tombert和密码。Windows shutdown
将正常关闭所有应用程序并关闭操作系统电源(通常)。然后使用连续检查虚拟机状态showvminfo
。在1秒钟的超时时间内至少执行60次(执行此处认为适当的操作),应使虚拟机有足够的时间正常关闭。请注意,showvminfo
还需要不到一秒钟的时间(至少在我的计算机上),因此在我的情况下大约需要120秒。如果一切都刹车了,我们可以使用该poweroff
语句强制关闭。
您还应该看到acpipowerbutton
,但未使用。这是因为它不能可靠地工作。如果您已登录Windows,或者什至有多个用户登录,Windows将显示一个确认关闭对话框,以防止系统关闭。这也是为什么的原因acpibutton
中/etc/default/virtualbox
是行不通的100%可靠。同时,poweroff
还将强行关闭虚拟机-与长按电源按钮相同。因此,最好将此设置为空:
摘自/ 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
SHUTDOWN_USERS=""
SHUTDOWN=""
为了使其更完美,您可能需要更改电源按钮的行为:
摘自/etc/acpi/powerbtn.sh:
#!/bin/sh
# /etc/acpi/powerbtn.sh
# Initiates a shutdown when the power putton has been
# pressed.
# @backup
# plain shutdown
/sbin/shutdown -h now "Power button pressed"
# fini
exit 0
...
...
还剩下一个小缺点。当虚拟机仍在引导且guest虚拟机控制服务未启动(在虚拟机中)时,它将不会收到shutdown命令。罕见的情况...但是请考虑一下。
就是这样,希望对您有所帮助。
VERR_INVALID_PARAMETER
如果我以脚本中给定的用户身份通过RDC登录后,它似乎在主机端抛出了一个问题,随后guest虚拟机继续运行。
按照此答案更改系统策略以进行重新引导
您无法将其简化为reboot
。AFAIK init.d
脚本将不起作用,因为它花费了太多时间,但是您可以运行以下命令:
VBoxManage controlvm <vm> savestate&&reboot
<vm>
虚拟机的名称在哪里
您可以使用以下方式向虚拟机发送关闭请求:
VBoxManage controlvm <vm_name> acpipowerbutton
但是,如果您在初始化脚本中执行此操作,则在关闭完成之前,脚本不应退出。我们可以通过lsof
或fuser
循环轮询VM的驱动器文件(.vdi)来检测到该错误。或者作为便宜的解决方法,sleep 20
可能就足够了。
这是我当前在初始化脚本的close块中使用的内容:
# This always returns 0, even if an error is displayed!
su - "$DAEMONUSER" VBoxManage controlvm "$VMNAME" acpipowerbutton
# Wait until the disk file is no longer open...
for attempt in `seq 1 20`
do
fuser "$VMDISKIMAGE" >/dev/null 2>&1 || break
sleep 2
done
return 0 # A better script would return success/fail
在我定义的文件顶部附近:
VMDISKIMAGE="/home/$DAEMONUSER/VirtualBox VMs/$VMNAME/$VMNAME.vdi"
这实际上可能不会关闭VirtualBox应用程序本身,但是会等待VM完成关闭。如果虚拟机仍在启动过程中(许多操作系统在此阶段忽略电源关闭按钮),或者您正在模拟不支持ACPI的旧系统,则它也不起作用。
reboot
在12.10中的手册页上说:“当使用--force调用时,或者在运行级别0或6中调用时,此工具将调用本身的reboot(2)系统调用并直接重新引导系统。否则,仅使用以下命令调用shutdown(8)工具:适当的论点。”;手册页上shutdown
说:“一旦经过了TIME,关机就会向init(8)守护程序发送一个请求,以将系统置于适当的运行级别。”