Đóng máy ảo một cách an toàn khi khởi động lại máy chủ


8

Tôi đang chạy Windows 7 bên trong Virtualbox trên Ubuntu 11.10. Mọi thứ đều hoạt động tốt. Tôi đang chạy nó khi khởi động, nhưng tôi gặp vấn đề với việc khởi động lại.

Khi tôi nhập sudo reboot nowtrạng thái của Windows 7 ảo không được lưu. Sau khi khởi động lại, hộp ảo bắt đầu, nhưng thay vì Windows đang chạy, tôi nhận được menu khởi động sự cố 7 của Windows và các cửa sổ sẽ khởi động lại.

Có một tùy chọn nào đó mà Ubuntu có thể gửi một số tín hiệu đến hộp ảo để đóng cá thể một cách an toàn trước khi khởi động lại máy chủ không?

Câu trả lời:


6

Trong trường hợp bạn thực sự cần tắt máy trong khi máy ảo trong Virtual Box đang chạy, bạn có thể xác định tập lệnh của riêng mình để tắt thủ công trong đó bạn đặt lệnh để lưu trạng thái máy trước khi quá trình tắt máy bắt đầu:

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

Ngoài ra, bạn cũng có thể tạo một tập lệnh luôn chạy khi tắt máy .


4

Nếu bạn sử dụng sudo rebootcác chương trình được cung cấp tín hiệu hủy kết thúc chúng tự động mà không cho ứng dụng thời gian để xử lý tình huống đó. Đây không phải là một lỗi, nó luôn hoạt động theo cùng một cách và đó là hành vi dự kiến.

Có một câu hỏi tương tự, nơi bạn có thể xem các lệnh được đưa ra khi bạn bấm shutdown, reboot, suspend, vv nút trên menu của người dùng, giải pháp như vậy nên yêu cầu bạn phải làm gì khi cố gắng để đóng một cửa sổ với một ứng dụng đang chạy và thích hợp của nó (trong trường hợp của bạn) để sudo shutdowntiếp cận. Có một cái nhìn


Có phải khởi động lại gần đây đã trở nên lịch sự hơn? Trang hướng dẫn reboottrong 12.10 cho biết "Khi được gọi bằng --force hoặc khi ở runlevel 0 hoặc 6, công cụ này sẽ tự gọi hệ thống khởi động lại (2) và khởi động lại hệ thống. Nếu không, điều này chỉ đơn giản gọi công cụ tắt máy (8) với những lý lẽ phù hợp. "; và trang man cho shutdownbiết "Một khi TIME đã trôi qua, tắt máy sẽ gửi một yêu cầu đến daemon init (8) để đưa hệ thống xuống runlevel thích hợp."
echristopherson

4

Tôi muốn giới thiệu một cách tiếp cận tinh vi hơn bao gồm một công việc mới bắt đầu, một kịch bản bắt đầu và dừng lại. Ví dụ tôi đang sử dụng Windows XP, vì thư mục chính của tôi cho phép sử dụng tombert ... mà bạn nên thay đổi cho phù hợp. Nó có lợi thế của bất cứ điều gì bạn làm (khởi động lại, tắt máy, nhấn nút nguồn) nó xử lý tốt máy ảo của bạn .

Đầu tiên, công việc mới bắt đầu, đưa vào /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

Công việc mới bắt đầu khởi động máy ảo trong runlevel 2 (ở chế độ đồ họa) và trong trường hợp của tôi, nó tăng mức độ ưu tiên với nice. Để tắt máy ảo, tôi cần "vô hiệu hóa" việc chấm dứt khởi động bằng cách sử dụng kill signal SIGCONTcâu lệnh. Điều này khiến máy ảo chạy lúc đầu (tránh mặc định SIGTERM). Sau 120 giây, SIGKILLdù sao đi nữa. Thay vào đó tôi đang chạy winxpvm-stop.shkịch bản.

Lưu ý phụ 1: Các khổ thơ start on started runlevel [2]stop on starting runlevel [!2]không hoạt động. Người ta phải đề cập cụ thể đến công việc rc.

Lưu ý phụ 2: Điều gì cũng khó hiểu từ hướng dẫn sử dụng mới bắt đầu: Đoạn kill signalthơ chỉ định tín hiệu được gửi sau 5 giây. Trong ví dụ này, tôi đặt nó từ SIGTERM(mặc định) thành SIGCONT - nhưng thời gian chờ 5 giây tôi không thể thay đổi. Đoạn kill timeoutthơ chỉ định thời gian chờ mà sau đó SIGKILLđược gửi - tín hiệu mà người ta không thể thay đổi. Do đó, một cải tiến sẽ là xác định khổ thơ mới term signalterm timeout.

Ở đây tập lệnh bắt đầu 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

Vì tất cả các cài đặt, v.v. được thực hiện trong chế độ người dùng (vì thông tin đăng nhập của tôi là tombert ), ngay cả khi chạy bằng root, tôi thay đổi tài khoản thành tombert . Người dùng tất nhiên có thể được thay đổi trong cấu hình khởi động nhưng giải pháp này cho tôi tùy chọn khởi động / dừng máy ảo "bằng tay" từ bảng điều khiển.

Điều thú vị hơn là kịch bản tắt máy trong 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

Đầu tiên tôi làm tương tự như trong tập lệnh bắt đầu - Tôi đang thay đổi người dùng từ root sang tài khoản tombert của tôi . Bây giờ hãy xem chức năng dostop. Đầu tiên tôi đang kiểm tra xem máy ảo có chạy không. Sau đó, tôi đang cố gắng "nhẹ nhàng" tắt máy bằng cách gửi tắt máy trực tiếp đến WinXP bằng cách sử dụng guestcontrol. Ở đây bạn phải cung cấp thông tin đăng nhập cho tài khoản WinXP, trong trường hợp của tôi là tombert và mật khẩu. Windows shutdownsẽ đóng một cách duyên dáng tất cả các ứng dụng và tắt nguồn hệ điều hành (thông thường). Sau đó cho phép kiểm tra trạng thái máy ảo liên tục bằng cách sử dụng showvminfo. Làm điều này ít nhất 60 lần với thời gian chờ 1 giây (làm bất cứ điều gì bạn nghĩ là phù hợp ở đây) sẽ khiến máy ảo đủ thời gian để tắt máy một cách duyên dáng. Lưu ý rằng cuộc gọi đếnshowvminfocũng mất ít hơn một chút (ít nhất là trên máy tính của tôi) vì vậy điều này mang lại cho nó ~ 120 giây trong trường hợp của tôi. Nếu mọi thứ phanh chúng ta có thể tắt máy mạnh mẽ bằng cách sử dụng poweroffcâu lệnh.

Bạn cũng nên xem acpipowerbutton, nhưng không sử dụng. Điều này là do nó không hoạt động đáng tin cậy. Nếu bạn đã đăng nhập vào Windows, hoặc thậm chí tệ hơn nhiều người dùng, Windows sẽ hiển thị hộp thoại tắt xác nhận ngăn hệ thống tắt máy. Đây cũng là lý do tại sao acpibuttontrong /etc/default/virtualboxsẽ không hoạt động đáng tin cậy 100%. Ngoài ra, poweroffsẽ tắt mạnh máy ảo - giống như một nút nguồn nhấn dài. Vì vậy, tốt nhất là đặt cái này thành trống:

Trích từ / 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=""

Để làm cho nó hoàn hảo, bạn có thể muốn thay đổi hành vi của nút nguồn:

Trích từ /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ó một nhược điểm nhỏ còn lại. Khi máy ảo vẫn khởi động và dịch vụ điều khiển khách không hoạt động (trong máy ảo), nó sẽ không nhận được lệnh tắt máy. Một trường hợp hiếm hoi ... nhưng hãy nghĩ về nó.

Đó là nó, hy vọng nó sẽ giúp.


Hoạt động như một bùa mê (khách Windows XP), ngoại trừ việc nó xuất hiện VERR_INVALID_PARAMETERở phía máy chủ nếu tôi đăng nhập qua RDC với tư cách là người dùng được cung cấp trong tập lệnh và sau đó khách tiếp tục chạy.
echristopherson

Tôi đã thử với cả hai, RDC gốc và với RDC trên VirtualBox. Không có lỗi như vậy. Có lẽ liên quan đến virtualbox.org/ticket/8197
tombert

2

Thực hiện theo câu trả lời này để thay đổi chính sách hệ thống của bạn để khởi động lại

Bạn không thể hợp lý hóa điều này vào reboot. Các init.dtập lệnh AFAIK sẽ không hoạt động vì mất quá nhiều thời gian, nhưng bạn có thể chạy lệnh như thế này:

VBoxManage controlvm <vm> savestate&&reboot

nơi <vm>là tên của Virtual Machine


1

Bạn có thể gửi yêu cầu tắt máy đến máy ảo với:

VBoxManage controlvm <vm_name> acpipowerbutton

Nhưng nếu bạn làm điều này trong một tập lệnh init, tập lệnh sẽ không thoát cho đến khi tắt máy hoàn tất. Chúng tôi có thể phát hiện ra điều đó bằng cách bỏ phiếu tệp ổ đĩa của VM (.vdi) bằng lsofhoặc fusertrong một vòng lặp. Hoặc như một cách giải quyết rẻ tiền, sleep 20có thể đủ.

Đây là những gì tôi hiện đang sử dụng trong khối đóng của tập lệnh init của tôi:

# 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

Gần đầu tập tin tôi xác định:

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

Điều này có thể không thực sự đóng ứng dụng VirtualBox, nhưng nó chờ VM hoàn tất tắt máy. Ngoài ra, nó không hoạt động nếu máy ảo vẫn đang trong quá trình khởi động (nhiều hệ điều hành bỏ qua nút tắt nguồn trong giai đoạn này) hoặc nếu bạn đang mô phỏng một hệ thống cũ không hỗ trợ ACPI.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.