使用Applescript关闭VMware Fusion虚拟机并安全备份它们

时间:2013-04-15 00:31:53

标签: applescript backup vmware virtual-machine fusion

VMware建议不使用Apple的Time Machine备份虚拟机(VM),除非使用快照。但是,许多高级,有经验的用户强烈反对使用快照,因为每个快照链都在前一个快照链上,这意味着任何链接的故障都可能导致VM出现故障,同时增加VM的复杂性并降低其性能

所以,我正在尝试编写AppleScript来关闭所有正在运行的VM,然后复制备份。这应该是干净而简单的。

但是,我遇到了暂停VM的一些问题(因此Boot Camp虚拟机不会出现问题,因为它们无法挂起)。如果VM被挂起,那么您需要将其关闭(关闭)以便干净地备份它。关闭已挂起的VM的唯一方法是先恢复它,然后关闭它。如果VM在自己的窗口中打开,那对AppleScript来说不是问题。 VMWare Fusion正确地将此VM报告为已暂停,允许脚本首先恢复它,然后将其关闭。

不幸的是,如果VM窗口已关闭,因此它没有自己的窗口,而只出现在虚拟机库中,则VMware Fusion无法正确报告VM已挂起。即使VM被挂起,VMware Fusion也会将该状态报告为“已关机”,这意味着将备份已挂起的VM。

您可以在此处找到其他详细信息:

http://communities.vmware.com/message/2227680#2227680

这是我的代码。非常欢迎反馈,建议和改进!

(*
Applescript application to auto back up virtual machines after certain period of system idle

Requirements:
[ ] "Power off the virtual machine" must be selected in VMWare Fusion "Preferences…" -> "General" -> "When closing a virtual machine:" -- this is needed because if a VM window is closed, then VMware reports the power state of a VM as "powered off" even if the VM is actually "suspended"; and from a document object there is no way to access its window
[ ] In "System Preferences…" -> "Energy Saver" -> "Power adapter" -> "Computer sleep" must be set to a greater value than backup_after + ( check_every * 2 )


http://culturedcode.com/forums/read.php?7,30174,30597

To make this runable, save as application.
To not show in Dock, set LSBackgroundOnly in Info.plist of created app bundle, or other ways in
http://groups.google.com/group/macenterprise/browse_thread/thread/be7db35451e1dc70
*)

property afterHours : 8 --23 -- hour of the day to start monitoring idle
property workDayStarts : 5 -- hour of the day to stop monitoring idle
property backupDuration : 2 -- number of hours needed to back up virtual machines

global backup_after, check_every -- TODO: do these really need to be global ?

set backup_after to 10 --(40 * 60) -- in seconds
set check_every to 5 --(10 * 60)

property cancelTimer : 60 -- how many seconds the user has to cancel backup

property virtualizationApp : "VMware Fusion" -- variable can't be used in 'tell application' statements or won't compile, so search & replace other instances of "VMware Fusion"
property resumeDelay : 120 --(4 * 60) -- in seconds; usually takes  backup_after then

                -- test to see if backup has been done today
                if my hasNotBackedUpToday(backupLocation) then

                    -- warn the user that VM application will force close VMs
                    repeat with secondsLeft from cancelTimer to 1 by -1
                        set dialogResult to display alert virtualizationApp & " is about to force quit and back up virtual machines " message "This AppleScript is set to force close " & virtualizationApp & ", if it's open, and its virtual machines, and then to back up the virtual machines." & return & return & "Click \"Cancel\" to delay these actions until later, or press \"OK\" to quit and back up." & return & return & secondsLeft & " seconds left." buttons {"OK", "Cancel"} default button "OK" as warning giving up after 1
                        if secondsLeft = 1 or (button returned of dialogResult) is "OK" then

                            -- force VMs to power off, quit VM app
                            my powerOffVMsQuitFusion()

                            -- back up VMs
                            if my backupVMs(backupLocation, virtualMachinesLocation) then
                                display dialog "Successfully backed up virtual machines."
                            else
                                display dialog "Failed to back up virtual machines."
                            end if

                            exit repeat
                        else if (button returned of dialogResult) is "Cancel" then
                            display dialog "Backup delayed until later."
                            exit repeat
                        end if
                    end repeat
                else
                    return (8 * 60 * 60) -- have backed up today, so try again in 8 hrs
                end if
            end if

            return check_every

        end if
    end tell
end idle


(*
 * Check to see if have backed up in last 16 hrs
 *)
on hasNotBackedUpToday(theLocation)
    tell application "Finder"
        set bLocation to POSIX file theLocation as alias
        sort (get folders of bLocation) by creation date
        set myResult to result
        set myResultCount to count of myResult

        -- this raises an error if the folder doesn't contain any files
        if (myResultCount is not equal to 0) then
            set theFile to (item 1 of myResult)
            if creation date of theFile is greater than ((current date) - (16 * 60 * 60)) then
                --display dialog "Have backed up today."
                return false
            end if
        end if

        -- delete a backup if have reached max
        if myResultCount ≥ numBackupsToKeep then
            delete item myResultCount of myResult
        end if

        set currDate to current date
        set folderName to ("" & (year of currDate) & "-" & (month of currDate) & "-" & (day of currDate))
        make new folder at bLocation with properties {name:folderName}

        return true
    end tell
end hasNotBackedUpToday


(*
 * force VMs to power off, quit VM app
 *)
on powerOffVMsQuitFusion()
    tell application "VMware Fusion"
        activate -- can't test to see if a VM is suspended unless VMware is running
        delay 10 -- give the application time to open

        repeat with currVM in documents
            set powerState to power state of currVM

            -- power off doesn't work on suspended VMs
            if powerState is suspended then -- VM reports powered off even when actually suspended, reports correctly if VM's own window open (VM Library, right-click on VM, then select "Show Windows")
                --display dialog "VM " & (name of currVM) & " is suspended"
                resume currVM -- only want to resume if actually suspended, otherwise it starts powered off VMs
                delay resumeDelay -- give VM time to resume
            end if

            if powerState is powered on then
                --display dialog "Name: " & (name of currVM)
                --display dialog "Name: " & (OS name of currVM)

                -- XP unsaved docs prevent power off unless with force, Win7 works without force
                try
                    (*if (OS name of currVM) contains "7" then
                        --display dialog "Win 7: would power off withOUT force"
                        power off currVM
                        delay powerOffDelay
                    else*)
                    --display dialog "Not Win 7 (XP, etc.): would power off with force"
                    power off currVM with force
                    --end if
                on error errMsg number errNum
                    tell application "Finder"
                        display dialog ("errMsg: " & errMsg & ", errNum: " & errNum)
                    end tell
                end try

            end if
        end repeat

        quit
        delay 5

    end tell
end powerOffVMsQuitFusion


(*
 * Back up VMs, deleting oldest backup if necessary
 *)
on backupVMs(thisLocation, thisVMsLocation)
    tell application "Finder"
        set thisBackupLocation to POSIX file thisLocation as alias
        sort (get folders of thisBackupLocation) by creation date
        set myFinderResult to result

        -- This raises an error if the folder doesn't contain any files
        if ((count of myFinderResult) = 0) then
            display dialog "Error. What happened to the folder that was just created?"
            return false
        else
            set backupFolder to (item 1 of myFinderResult)
            --display dialog "Folder name: " & (name of backupFolder)

            -- check to see if folder is empty
            if ((count files of backupFolder) is not equal to 0) then
                display dialog "Error. Backup folder wasn't empty."
                return false
            end if

            -- copy virtual machines to backup folder
            --set vmsLocation to alias "Macintosh HD:Users:mikeong:Documents:Virtual Machines"
            set vmsLocation to alias thisVMsLocation
            duplicate every file of vmsLocation to backupFolder

            return true
        end if
    end tell
end backupVMs

1 个答案:

答案 0 :(得分:0)

您可能希望查看以下脚本:http://www.lbackup.org/developer/vmware_fusion_virtual_machine_backup

我怀疑是一些小的改动,它会关闭VM而不是暂停VM。