Eu recomendaria uma abordagem mais sofisticada, incluindo um trabalho inicial, um script de início e parada. Como exemplo, estou usando o Windows XP, já que meu diretório pessoal permite usar tombert ... que você deve alterar de acordo. Tem a vantagem de fazer o que fizer (reiniciar, desligar, pressionar o botão liga / desliga) e manipular sua máquina virtual bem .
Primeiro o trabalho inicial, coloque em /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
O job upstart inicia a máquina virtual no nível de execução 2 (que está no modo gráfico) e, no meu caso, aumenta a prioridade com nice
. Para desligar a máquina virtual, preciso "desabilitar" a terminação inicial usando a instrução kill signal SIGCONT
. Isso deixa a máquina virtual em execução no início (evitando o padrão SIGTERM
). Após 120 segundos, o SIGKILL
é enviado de qualquer forma. Em vez disso, estou executando o script winxpvm-stop.sh
.
Side-Note 1: As sub-rotinas start on started runlevel [2]
e stop on starting runlevel [!2]
não funcionam. É preciso mencionar especificamente o trabalho rc
.
Side-Note 2: O que também é confuso no manual do upstart: A estrofe kill signal
especifica o sinal enviado após 5 segundos. Neste exemplo, eu o configurei de SIGTERM
(padrão) para SIGCONT - mas o tempo limite de 5 segundos não consegui mudar. A sub-rotina kill timeout
especifica o tempo limite após o qual o SIGKILL
é enviado - qual sinal não é possível alterar. Uma melhoria, portanto, seria definir novas estrofes term signal
e term timeout
.
Aqui o script de início 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
Como todas as configurações, etc., são feitas no modo de usuário (como meu login é tombert ), mesmo quando executado como root, altero a conta para tombert . O usuário, claro, poderia ser alterado na configuração inicial, mas essa solução me deixa a opção de iniciar / parar a máquina virtual "manualmente" no console.
O mais interessante é o script de desligamento em 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
Primeiro, faço o mesmo que no script de início - estou mudando o usuário do root para minha conta tombert . Agora vamos ver a função dostop
. Primeiro, estou verificando se a máquina virtual está funcionando. Então eu estou tentando desligar "suavemente" enviando um desligamento diretamente para o WinXP usando guestcontrol
. Aqui você deve fornecer as credenciais para a conta do WinXP, que no meu caso é tombert e uma senha. O Windows shutdown
fechará todos os aplicativos e desligará o sistema operacional (normalmente). Em seguida, vamos verificar o estado da máquina virtual continuamente usando showvminfo
. Fazendo isso pelo menos 60 vezes com tempo limite de 1 segundo (faça o que achar apropriado) deve deixar a máquina virtual com tempo suficiente para desligar normalmente. Note que a chamada para showvminfo
também leva um pouco menos de um segundo (pelo menos no meu computador), então isso dá ~ 120 segundos no meu caso. Se tudo travar, poderemos desligar com força usando a instrução poweroff
.
Você também deve ver o acpipowerbutton
, mas não usado. Isso ocorre porque não funciona de forma confiável. Se você estiver conectado ao Windows ou, pior ainda, vários usuários, o Windows mostrará uma caixa de diálogo de confirmação de desligamento evitando que o sistema seja desligado. Essa também é a razão pela qual o acpibutton
no /etc/default/virtualbox
não funcionará 100% confiável. Além disso, o poweroff
forçará o desligamento da máquina virtual - da mesma forma que um botão liga / desliga pressionado por muito tempo. Portanto, é melhor definir isso como vazio:
Trecho de / 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=""
Para torná-lo perfeito, talvez você queira alterar o comportamento do botão liga / desliga:
Trecho de /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
...
...
Existe um pequeno inconveniente. Quando a máquina virtual ainda está inicializando e o serviço de controle de convidados não está ativo (na máquina virtual), ele não receberá o comando de desligamento. Um caso raro ... mas pense nisso.
É isso, espero que ajude.