Я бы порекомендовал более сложный подход, включающий в себя выскочившую работу, скрипт запуска и остановки. В качестве примера я использую 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
. Выполнение этого как минимум 60 раз с 1-секундным таймаутом (делайте все, что вы считаете подходящим здесь) должно дать виртуальной машине достаточно времени для корректного завершения работы. Обратите внимание, что призыв к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
...
...
Остался один маленький недостаток. Когда виртуальная машина все еще загружается, а служба гостевого управления не запущена (на виртуальной машине), она не получит команду выключения. Редкий случай ... но подумай об этом.
Вот и все, надеюсь, это поможет.
reboot
12.10 сообщает: «При вызове с помощью --force или при уровне запуска 0 или 6 этот инструмент вызывает сам системный вызов reboot (2) и напрямую перезагружает систему. В противном случае это просто вызывает инструмент shutdown (8) с соответствующие аргументы. "; и на странице руководстваshutdown
говорится: «По истечении ВРЕМЕНИ shutdown отправляет запрос демону init (8) о переводе системы на соответствующий уровень выполнения».