前言

最近拿闲置电脑装了个Win11作为NAS使用,感觉Windows NAS也没有那么不堪用了,顺便使用Windows自带的Hyper-V作为虚拟机平台使用,对比Proxmox和ESXi,能用,但又不是很好用,甚至没有自动化创建快照的功能,好在PowerShell提供了接口,就写个脚本完成定时创建快照

脚本正文

$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)

# 如果不是管理员,以管理员身份重新运行脚本
if (-not $isAdmin) {
    Start-Process powershell -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs
    Exit
}

# 此处放置你的脚本的其余部分
Write-Output "脚本以管理员身份运行"

# 保留的最大快照数量
$maxSnapshots = 14

# 获取所有虚拟机的名称
$vms = Get-VM
foreach ($vm in $vms) {
    Write-Output "为虚拟机 $($vm.Name) 创建定时快照"

    $datetime = Get-Date -Format 'yyyy-MM-dd tt hh:mm:ss'
    # 创建快照
    Checkpoint-VM -VM $vm -SnapshotName "定时快照 ($datetime)"

    # 获取所有快照
    $snapshots = Get-VMSnapshot -VM $vm | Where-Object { $_.Name -like '定时快照*' }
    Write-Output "共有 $($snapshots.Count) 个定时快照"

    # 如果快照数量超过限制,则删除较旧的快照
    if ($snapshots.Count -gt $maxSnapshots) {
        $snapshotsToDelete = $snapshots | Sort-Object CreationTime | Select-Object -First ($snapshots.Count - $maxSnapshots)

        foreach ($snapshot in $snapshotsToDelete) {
            Write-Output "删除快照 $($snapshot.Name)"
            Remove-VMSnapshot -VM $vm -Name $snapshot.Name
        }
    }
}

记得用 UTF8-with-BOM 编码保存,否则脚本中的中文会乱码

添加定时任务

如果没有设置过脚本执行策略的话Windows默认禁止执行脚本,用命令改成允许本地脚本执行,远程脚本需要签名才能执行

Set-ExecutionPolicy RemoteSigned

然后在任务计划程序(taskschd.msc)中添加新的任务
2024-01-10T03:25:15.png
操作Hyper-V需要提权,一定要勾选使用最高权限运行

2024-01-10T03:24:43.png
触发器就是什么时间执行任务,按需设置,我这里设的是一天备份两次

2024-01-10T03:26:48.png
操作就是执行的动作,添加一条启动程序的操作,程序或脚本填powershell -File 脚本文件路径

2024-01-10T03:28:18.png
保存需要输入当前的账户密码,然后在右侧菜单手动执行一下任务

2024-01-10T03:29:22.png
如果一切正常就可以在Hyper-V管理器中看见脚本创建的快照了

最后修改:2024 年 01 月 10 日
Null