Chiudi in modo sicuro la macchina virtualbox al riavvio dell'host


8

Sto eseguendo Windows 7 all'interno di Virtualbox su Ubuntu 11.10. Tutto funziona bene. Lo sto eseguendo all'avvio, ma ho un problema con il riavvio.

Quando digito sudo reboot nowlo stato di Windows 7 virtuale non viene salvato. Dopo il riavvio la virtualbox si avvia, ma invece di Windows in esecuzione ottengo il menu di avvio di Windows 7 e Windows si riavvia nuovamente.

Esiste un'opzione che Ubuntu potrebbe inviare un segnale alla scatola virtuale per chiudere in sicurezza l'istanza prima del riavvio dell'host?

Risposte:


6

Nel caso in cui sia davvero necessario arrestare il sistema mentre è in esecuzione una macchina virtuale in Virtual Box, è possibile definire il proprio script per un arresto manuale in cui si inserisce un comando per salvare lo stato del computer prima dell'avvio del processo di arresto:

VBoxManage controlvm <name> savestate # <name> is the name of your VM
gnome-session-quit --power-off # this example displays the power-off dialog for >11.10

In alternativa, potresti anche generare uno script che viene sempre eseguito allo spegnimento .


4

Se si utilizzano i sudo rebootprogrammi, viene dato il segnale di interruzione terminandoli automaticamente senza dare a un'applicazione il tempo di agire su tale situazione. Questo non è un bug, ha sempre funzionato allo stesso modo e questo è il comportamento previsto.

V'è una domanda simile in cui è possibile vedere quali comandi sono dati quando si preme il shutdown, reboot, suspend, ecc pulsante del menu utente, tale soluzione dovrebbe chiedere che cosa fare quando si cerca di chiudere una finestra con un'applicazione in esecuzione e il suo preferibili (in il tuo caso) sudo shutdownall'approccio. Dare un'occhiata


Il riavvio è diventato recentemente più educato? La pagina man di rebootin 12.10 dice "Quando viene chiamato con --force o quando nel runlevel 0 o 6, questo strumento richiama la stessa chiamata di sistema reboot (2) e riavvia direttamente il sistema. Altrimenti questo semplicemente invoca lo strumento shutdown (8) con gli argomenti appropriati. "; e la pagina man per shutdowndice "Una volta che TIME è trascorso, shutdown invia una richiesta al demone init (8) per portare il sistema nel runlevel appropriato."
ecristopherson,

4

Consiglierei un approccio più sofisticato che includa un lavoro iniziale, uno script di avvio e arresto. Ad esempio, sto usando Windows XP, poiché la mia directory home consente di usare Tombert ... che dovresti cambiare di conseguenza. Ha il vantaggio di qualsiasi cosa tu faccia (riavvio, spegnimento, premendo il pulsante di accensione) gestisce bene la tua macchina virtuale .

Innanzitutto il processo di avvio, inserisci in /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

Il processo di avvio avvia la macchina virtuale nel runlevel 2 (che è in modalità grafica) e nel mio caso aumenta la priorità con nice. Per arrestare correttamente la macchina virtuale, è necessario "disabilitare" la terminazione di avvio utilizzando l' kill signal SIGCONTistruzione. Ciò lascia inizialmente la macchina virtuale in esecuzione (evitando l'impostazione predefinita SIGTERM). Dopo 120 secondi SIGKILLviene comunque inviato. Invece sto eseguendo la winxpvm-stop.shsceneggiatura.

Nota a margine 1: le stanze start on started runlevel [2]e stop on starting runlevel [!2]non funzionano. Bisogna menzionare specificamente il lavoro rc.

Nota a margine 2: Ciò che confonde anche dal manuale di avvio: La kill signalstanza specifica il segnale inviato dopo 5 secondi. In questo esempio l'ho impostato da SIGTERM(impostazione predefinita) a SIGCONT, ma il timeout di 5 secondi non sono stato in grado di modificare. La kill timeoutstanza specifica il timeout dopo il quale SIGKILLviene inviato - quale segnale non è possibile modificare. Un miglioramento sarebbe quindi quello di definire nuove stanze term signale term timeout.

Ecco lo script iniziale 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

Dal momento che tutte le impostazioni ecc. Vengono eseguite in modalità utente (poiché il mio accesso è tombert ), anche quando eseguito come root, cambio l'account in tombert . L'utente ovviamente potrebbe essere modificato nella configurazione di avvio ma questa soluzione mi lascia la possibilità di avviare / arrestare la macchina virtuale "a mano" dalla console.

Il più interessante è lo script di arresto in 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

Per prima cosa faccio lo stesso dello script iniziale: sto cambiando l'utente da root a Tombert . Ora diamo un'occhiata alla funzione dostop. Innanzitutto sto verificando se la macchina virtuale è persino in esecuzione. Quindi sto cercando di arrestare "dolcemente" l'invio di un arresto direttamente a WinXP utilizzando guestcontrol. Qui devi fornire le credenziali per l'account WinXP, che nel mio caso è Tombert e una password. Windows shutdownchiuderà con grazia tutte le applicazioni e spegnerà il sistema operativo (normalmente). Quindi consente di controllare continuamente lo stato della macchina virtuale showvminfo. Farlo almeno 60 volte con 1 secondo di timeout (fare qualsiasi cosa tu pensi che sia giusto qui) dovrebbe lasciare alla macchina virtuale abbastanza tempo per spegnersi con grazia. Si noti che la chiamata ashowvminforichiede anche un po 'meno di un secondo (almeno sul mio computer) quindi questo mi dà ~ 120 secondi nel mio caso. Se tutto frena, possiamo forzare l'arresto usando l' poweroffistruzione.

Dovresti anche vedere il acpipowerbutton, ma non utilizzato. Questo perché non funziona in modo affidabile. Se hai effettuato l'accesso a Windows o, peggio ancora, più utenti, Windows mostrerà una finestra di dialogo di arresto di conferma che impedisce al sistema di arrestarsi. Questo è anche il motivo per cui acpibuttonin the /etc/default/virtualboxnon funzionerà al 100% affidabile. Inoltre poweroffspegnerà forzatamente la macchina virtuale, come un pulsante di accensione a pressione prolungata. Pertanto è meglio impostare questo su vuoto:

Estratto da / 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=""

Per renderlo perfetto potresti voler cambiare il comportamento del pulsante di accensione:

Estratto da /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
...
...

C'è ancora un piccolo inconveniente. Quando la macchina virtuale è ancora in fase di avvio e il servizio di controllo guest non è attivo (nella macchina virtuale) non riceverà il comando di arresto. Un caso raro ... ma pensaci.

Questo è tutto, spero che sia d'aiuto.


Funziona come un incantesimo (guest di Windows XP), tranne per il fatto che sembra essere stato lanciato VERR_INVALID_PARAMETERsul lato host se sono connesso tramite RDC come utente indicato nello script, e successivamente l'ospite continua a funzionare.
ecristopherson,

Ho provato con entrambi, RDC nativo e con RDC su VirtualBox. Nessun errore del genere. Probabilmente correlato a
virtualbox.org/ticket/8197

2

Segui questa risposta per modificare i criteri di sistema per il riavvio

Non puoi semplificare questo in reboot. Gli init.dscript AFAIK non funzioneranno perché richiede troppo tempo, ma puoi eseguire il comando in questo modo:

VBoxManage controlvm <vm> savestate&&reboot

dove si <vm>trova il nome della macchina virtuale


1

È possibile inviare una richiesta di arresto alla macchina virtuale con:

VBoxManage controlvm <vm_name> acpipowerbutton

Ma se lo fai in uno script init, lo script non dovrebbe uscire fino al completamento dell'arresto. Potremmo essere in grado di rilevarlo eseguendo il polling del file di unità della VM (.vdi) con lsofo fuserin un ciclo. O come soluzione alternativa economica, sleep 20può essere sufficiente.

Ecco cosa sto attualmente usando nel blocco vicino del mio script init:

# 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

Nella parte superiore del file che ho definito:

VMDISKIMAGE="/home/$DAEMONUSER/VirtualBox VMs/$VMNAME/$VMNAME.vdi"

Questo in realtà potrebbe non chiudere l'app VirtualBox stessa, ma attende che la VM completi l'arresto. Inoltre, non funziona se la macchina virtuale è ancora in fase di avvio (molti sistemi operativi ignorano il pulsante di spegnimento durante questa fase) o se si sta emulando un vecchio sistema senza supporto ACPI.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.