Windows Server 2016中PowerShell备份清理脚本未删除文件夹
PowerShell备份清理脚本在Windows Server 2016中不执行删除操作排查与修复
问题描述
编写的PowerShell脚本用于删除备份文件夹并保留最新3个,测试环境通过任务计划执行正常,但部署到Windows Server 2016后:
- 脚本能正常执行并发送完成通知邮件
- 可检测到备份文件夹名称,但实际未执行删除操作
- 已将备份目录移至服务器本地、设置执行策略为
RemoteSigned,问题仍存在
原脚本如下:
# Gets path of Backup folder $backup_path = 'C:\Backup' # Getting the subfolders inside the Backup folder $subfolders = Get-ChildItem -Path $backup_path -Directory -Force # Checks if the number of folders is more than 3** if ($subfolders.Count -gt 3) { # Sort subfolders by Creation Time $sorted_subfolders = $subfolders | Sort-Object -Property CreationTime # Getting number of subfolders to delete $delete_count = $subfolders.Count - 3 # Deletes the subfolders and their contents $sorted_subfolders[0..($delete_count - 1)] | Remove-Item -Force -Recurse -ErrorAction SilentlyContinue # Write a message to the console when deletion complete Write-Output "Deleted $($delete_count) subfolders" # Create a string for email with the folder names $email_body = "The Backup Management Script Has been Executed Successfully!`n`n" + "The following folders were deleted from the SQL backup folder:`n" + ($sorted_subfolders[0..($delete_count - 1)].Name -join "`n") + "`n`n" + "The following folders are left in the SQL backup folder:`n" + ($sorted_subfolders[$delete_count..($subfolders.Count - 1)].Name -join "`n") } else { # Writes email to Admin when Latest 3 Backup folders are left** $email_body = "No backup Folder Older than 3 Days Have been Found!`n Please Check If the Backup has run as scheduled." } # Sends email notification $SmtpClient = new-object system.net.mail.smtpClient $MailMessage = New-Object system.net.mail.mailmessage $SmtpClient.Host = "SMTP server IP" $mailmessage.from = ("Noreply.backup@domain.com") $mailmessage.To.add("Admin@domain.com") $mailmessage.Subject = "Backup Cleanup Job" $mailmessage.Body = $email_body $smtpclient.Send($mailmessage)
排查与修复方案
1. 任务计划执行权限不足
Windows Server 2016的任务计划默认可能使用低权限账户(如本地系统账户)运行,而C:\Backup目录需要管理员权限才能删除文件。
- 解决:编辑任务计划,在「安全选项」中勾选使用最高权限运行,并确保执行账户对
C:\Backup目录拥有完全控制权限。
2. 错误被静默屏蔽无法定位问题
原脚本中Remove-Item使用-ErrorAction SilentlyContinue,会掩盖所有删除错误,导致无法知道失败原因。
- 解决:临时移除该参数,或改为
-ErrorAction Stop并添加错误捕获,例如:
try { $sorted_subfolders[0..($delete_count - 1)] | Remove-Item -Force -Recurse -ErrorAction Stop Write-Output "Deleted $($delete_count) subfolders" } catch { $email_body = "删除操作失败:`n$($_.Exception.Message)" }
3. 排序逻辑不符合实际备份场景
按CreationTime排序可能不准确——部分备份工具会复用文件夹,此时LastWriteTime更能反映备份的最新状态。
- 解决:修改排序属性为
LastWriteTime:
$sorted_subfolders = $subfolders | Sort-Object -Property LastWriteTime
4. 数组索引边界优化
原脚本用索引切片0..($delete_count -1)存在边界计算风险,改用Select-Object -First更直观可靠:
$foldersToDelete = $sorted_subfolders | Select-Object -First $delete_count $foldersToDelete | Remove-Item -Force -Recurse -ErrorAction Stop
5. 任务计划的PowerShell调用方式修正
Windows Server 2016中任务计划调用PowerShell时,需指定完整路径并明确执行参数:
- 程序/脚本:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe - 添加参数:
-ExecutionPolicy RemoteSigned -File "C:\你的脚本路径\CleanupBackup.ps1"
修改后的完整脚本
# 备份文件夹路径 $backup_path = 'C:\Backup' # 获取备份文件夹下的子目录 $subfolders = Get-ChildItem -Path $backup_path -Directory -Force # 判断子目录数量是否超过3个 if ($subfolders.Count -gt 3) { # 按最后修改时间排序(更贴合备份更新逻辑) $sorted_subfolders = $subfolders | Sort-Object -Property LastWriteTime # 计算需要删除的文件夹数量 $delete_count = $subfolders.Count - 3 # 筛选待删除和剩余的文件夹 $foldersToDelete = $sorted_subfolders | Select-Object -First $delete_count $remainingFolders = $sorted_subfolders | Select-Object -Last 3 try { # 执行删除操作 $foldersToDelete | Remove-Item -Force -Recurse -ErrorAction Stop Write-Output "已删除 $($delete_count) 个文件夹" # 构建成功通知邮件内容 $email_body = "备份清理脚本执行成功!`n`n" + "已从SQL备份目录删除以下文件夹:`n" + ($foldersToDelete.Name -join "`n") + "`n`n" + "SQL备份目录剩余以下文件夹:`n" + ($remainingFolders.Name -join "`n") } catch { # 构建错误通知邮件内容 $email_body = "备份清理脚本执行失败!`n`n错误信息:`n$($_.Exception.Message)" } } else { # 文件夹数量不足3个时的通知内容 $email_body = "未找到超过3个的备份文件夹!`n请检查备份任务是否按计划执行。" } # 发送邮件通知 $SmtpClient = New-Object system.net.mail.smtpClient $MailMessage = New-Object system.net.mail.mailmessage $SmtpClient.Host = "SMTP server IP" $mailmessage.from = ("Noreply.backup@domain.com") $mailmessage.To.add("Admin@domain.com") $mailmessage.Subject = "备份清理任务通知" $mailmessage.Body = $email_body $smtpclient.Send($mailmessage)
内容的提问来源于stack exchange,提问作者Omer Tirmizi
相关产品推荐
相关产品推荐

