概述
对于较小的环境,这通常不是一个问题,但如果您的环境较大,例如有10台以上的ESXi主机那么这可能成为一个重复性的问题,或者更现实地说,有一种更简单、更少手动操作的方法来实现,而不是启用SSH、运行命令、下载文件,然后禁用SSH。
有一个拥有22台ESXi主机的客户经常需要备份,但每次手动备份所有这些主机需要几个小时。
所以我将使用PowerCLI,通过简单地将脚本指向vCenter然后将其存储在某个安全的地方来自动化。
安装PowerCLI
从Windows PowerShell 安装 PowerCLI
Install-Module VMware.PowerCLI -Scope CurrentUser
同时可以参考:《VMware PowerCLI 安装使用指南》
如果系统是Ubuntu
#更新系统包 sudo apt-get update #安装先决条件包 sudo apt-get install -y wget apt-transport-https software-properties-common #获取带有 Ubuntu 版本 source /etc/os-release #下载仓库密钥 wget -q https://packages.microsoft.com/config/ubuntu/$VERSION_ID/packages-microsoft-prod.deb #注册 Microsoft 仓库密钥 sudo dpkg -i packages-microsoft-prod.deb #再次更新软件包列表 sudo apt-get update #安装 PowerShell sudo apt-get install -y powershell #进入PowerShell pwsh #从PowerShell安装PowerCLI Install-Module VMware.PowerCLI -Scope CurrentUser
Powershell脚本
有几个地方你需替换
$basePath - 定义备份基础路径 $vcUsername - 定义vCenter连接凭据 $vcPassword - 定义vCenter连接密码 $vcServer - 定义VCSA的FQDN
完整脚本
# ESXi主机配置备份脚本
# 描述:连接vCenter备份所有ESXi主机配置,并自动清理历史备份
# 定义备份基础路径
$basePath = "C:\ESXi-Config-Backups"
# 创建日志记录函数(需在调用前定义)
function Write-Log {
param (
[string]$Message,
[string]$LogPath = $script:logFilePath
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logMessage = "[$timestamp] $Message"
# 输出到控制台
Write-Output $logMessage
# 追加到日志文件
if ($LogPath) {
$logMessage | Out-File -FilePath $LogPath -Append -Encoding UTF8
}
}
# 检查基础路径是否存在,不存在则创建
if (-not (Test-Path -Path $basePath)) {
try {
New-Item -ItemType Directory -Path $basePath -Force | Out-Null
Write-Log "已创建基础备份路径: $basePath"
}
catch {
throw "无法创建基础备份路径: $basePath. 错误: $_"
}
}
# 获取当前时间(用于文件夹命名)
$currentDateTime = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
$backupFolderPath = Join-Path -Path $basePath -ChildPath $currentDateTime
# 创建本次备份文件夹
try {
New-Item -ItemType Directory -Path $backupFolderPath -Force | Out-Null
Write-Log "已创建备份文件夹: $backupFolderPath"
}
catch {
throw "无法创建备份文件夹: $backupFolderPath. 错误: $_"
}
# 创建日志文件路径
$logFilePath = Join-Path -Path $backupFolderPath -ChildPath "BackupLog.txt"
# 记录脚本开始
Write-Log "===== ESXi配置备份脚本开始执行 =====" -LogPath $logFilePath
try {
# 1. 临时禁用SSL证书验证
Write-Log "正在临时禁用SSL证书验证..." -LogPath $logFilePath
Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false -Scope Session | Out-Null
Write-Log "SSL证书验证已临时禁用" -LogPath $logFilePath
# 2. 断开所有现有vCenter连接
$existingConnections = @(Get-VIServer -ErrorAction SilentlyContinue)
if ($existingConnections.Count -gt 0) {
Write-Log "发现现有连接,正在断开..." -LogPath $logFilePath
Disconnect-VIServer -Server * -Force -Confirm:$false -ErrorAction SilentlyContinue | Out-Null
Write-Log "已断开所有现有vCenter连接" -LogPath $logFilePath
}
# 3. 定义vCenter连接凭据(建议从安全存储或加密文件读取)
$vcUsername = "<service-account>"
$vcPassword = "<password>"
$vcServer = "<vCenter-fqdn>"
# 创建安全凭据对象
$securePassword = ConvertTo-SecureString $vcPassword -AsPlainText -Force
$vcCredential = New-Object System.Management.Automation.PSCredential ($vcUsername, $securePassword)
# 4. 连接到vCenter服务器
Write-Log "正在连接到vCenter服务器: $vcServer" -LogPath $logFilePath
try {
$connection = Connect-VIServer -Server $vcServer -Credential $vcCredential -ErrorAction Stop
Write-Log "成功连接到vCenter: $($connection.Name)" -LogPath $logFilePath
}
catch {
throw "连接vCenter失败: $_"
}
# 5. 获取所有ESXi主机
Write-Log "正在获取ESXi主机列表..." -LogPath $logFilePath
try {
$esxiHosts = Get-VMHost -ErrorAction Stop
Write-Log "找到 $($esxiHosts.Count) 台ESXi主机" -LogPath $logFilePath
}
catch {
throw "获取ESXi主机列表失败: $_"
}
# 6. 遍历每台主机执行备份
$successCount = 0
$failedCount = 0
foreach ($esxiHost in $esxiHosts) {
$hostName = $esxiHost.Name
Write-Log "正在备份主机: $hostName" -LogPath $logFilePath
try {
# 执行固件配置备份
$backupResult = Get-VMHostFirmware -VMHost $esxiHost -BackupConfiguration -DestinationPath $backupFolderPath -ErrorAction Stop
$successCount++
Write-Log "✓ 主机 $hostName 备份完成" -LogPath $logFilePath
}
catch {
$failedCount++
Write-Log "✗ 主机 $hostName 备份失败: $_" -LogPath $logFilePath
continue
}
}
# 7. 备份完成统计
Write-Log "备份完成统计: 成功 $successCount 台, 失败 $failedCount 台" -LogPath $logFilePath
# 8. 清理旧备份(保留30天内的备份)
$retentionDays = 30
Write-Log "正在清理 $retentionDays 天前的旧备份..." -LogPath $logFilePath
$oldFolders = Get-ChildItem -Path $basePath -Directory |
Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$retentionDays) }
if ($oldFolders.Count -gt 0) {
$deletedCount = 0
foreach ($folder in $oldFolders) {
try {
Remove-Item -Path $folder.FullName -Recurse -Force -ErrorAction Stop
$deletedCount++
Write-Log "已删除旧备份文件夹: $($folder.Name)" -LogPath $logFilePath
}
catch {
Write-Log "删除文件夹失败: $($folder.Name). 错误: $_" -LogPath $logFilePath
}
}
Write-Log "已清理 $deletedCount 个旧备份文件夹" -LogPath $logFilePath
}
else {
Write-Log "没有需要清理的旧备份文件夹" -LogPath $logFilePath
}
# 9. 断开vCenter连接
Write-Log "正在断开vCenter连接..." -LogPath $logFilePath
Disconnect-VIServer -Server $vcServer -Confirm:$false -ErrorAction SilentlyContinue
Write-Log "已断开vCenter连接" -LogPath $logFilePath
# 10. 恢复SSL证书验证设置
Write-Log "正在恢复SSL证书验证设置..." -LogPath $logFilePath
Set-PowerCLIConfiguration -InvalidCertificateAction Prompt -Confirm:$false -Scope Session | Out-Null
Write-Log "SSL证书验证设置已恢复" -LogPath $logFilePath
# 最终总结
Write-Log "所有备份操作已完成" -LogPath $logFilePath
Write-Log "备份文件保存在: $backupFolderPath" -LogPath $logFilePath
Write-Log "日志文件位置: $logFilePath" -LogPath $logFilePath
Write-Log "===== 脚本执行完成 =====" -LogPath $logFilePath
}
catch {
# 异常处理
$errorMessage = "脚本执行失败: $_"
Write-Log $errorMessage -LogPath $logFilePath
Write-Error $errorMessage
# 尝试恢复SSL设置
try {
Set-PowerCLIConfiguration -InvalidCertificateAction Prompt -Confirm:$false -Scope Session | Out-Null
Write-Log "已恢复SSL证书验证设置" -LogPath $logFilePath
}
catch {
Write-Log "恢复SSL设置失败: $_" -LogPath $logFilePath
}
throw $errorMessage
}
执行脚本后将得到一个像这样的文件夹

任务计划
通过创建任务计划来实现自动化。
Windows系统
点击任务计划程序库,然后右键点击并点击创建任务

给它命名,勾选单选按钮只在用户登录时运行,设置每天运行的时间,设置程序为:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
在添加参数中添加
-ExecutionPolicy Bypass -File “脚本文件路径
点击条件并取消仅在交流电供电时运行的选项,

点击设置并取消勾选框以停止任务运行超过3天。

Ubuntu系统
使用 crontab
crontab -e
在底部添加
0 17 * * * pwsh /home/rpzm/Scripts/ESXi-Config-Backup.ps1 #替换为实际路径
1
管理多台主机,是要有些批处理的手段才行😃 博主的feed订阅不上不知道什么原因。