好的 - 我是PowerShell的新手。我两周前才开始使用它。我已经在网上搜索创建了一些脚本,现在我正在尝试一些看似有点高级的东西,我不确定如何解决这个问题。
我正在创建一个审核脚本,以确定两个备份存储库之间的文件有何不同,以确保它们已正确同步(同步脚本使用robocopy,并且它们在不产生错误的情况下多次失败)。这些文件夹非常广泛,有时,我发现脚本只挂在某些文件夹上(总是在最大的文件夹上),因此不会完成。
起初,我在完整的源路径上使用Get-ChildItem,但是这会产生内存问题,脚本永远不会完成。所以,我以为我会枚举子目录并在每个子目录上执行比较......但是根据文件夹,这也会变坏。
这是脚本(使用Powershell 2):
$serverArray=@("Server1","Server2","Server3")
for ($i=0; $i -lt 8; $i++) {
$server = $serverArray[$i]
$source="\\$server\Share\"
$destination = "D:\BackupRepository\$server"
# Copy to removable drive
$remoteDestination = "T:\BackupRepository\" + $server
$log = $server + "ShareBackup.log"
$remoteLog = "Remote_" + $server + "ShareBackup.log"
$logDestination = $localLogPath + $log
$logUNCDestination = $uncLogPath + $log
$logRemoteDestination = $localLogPath + $remoteLog
$logUNCRemoteDestination = $uncLogPath + $remoteLog
## This file is used for the process of checking
## whether or not the backup was successful
$backupReport = $localReportPath + $server + "ShareBackupReport.txt"
$remoteBackupReport = $localReportPath + "Remote_" + $server + "ShareBackupReport.txt"
## Variables for the failure emails
$failEmailSubject = "AUDIT REPORT for " + $server
$failRemoteEmailSubject = "AUDIT REPORT for " + $server
$failEmailBody = "The Audit for " + $server + " has found a file mismatch. Please consult the attached Backup Report."
$failRemoteEmailBody = "The Audit of the Remote Backups for " + $server + " has found a file mismatch. Please consult the attached Backup Report."
$sourceFolderArray = Get-ChildItem $source | ?{ $_.PSIsContainer }
$sourceFolderCount = $sourceFolderArray.Count
$mismatchCount = 0
$remoteMismatchCount = 0
for ($s1=0; $s1 -lt $sourceFolderCount; $s1++) {
$sourceFolder = $sourceFolderArray[$s1].FullName
$sourceFolderName = $sourceFolderArray[$s1].Name
$destFolder = $destination + "\" + $sourceFolderName
$remoteDestFolder = $remoteDestination + "\" + $sourceFolderName
Write-Host "Currently working on: " $sourceFolderName
$shot1 = Get-ChildItem -recurse -path $sourceFolder
$shot2 = Get-ChildItem -recurse -path $destFolder
$shot3 = Get-ChildItem -recurse -path $remoteDestFolder
$auditReportDest = "C:\BackupReports\Audits\"
$auditReportOutput = $auditReportDest + $server + "_" + $sourceFolderName + ".txt"
$auditReportRemoteOutput = $auditReportDest + $server + "_Remote_" + $sourceFolderName + ".txt"
$auditMismatchReport = $auditReportDest + "MismatchReport_" + $numericDate + ".txt"
Compare-Object $shot1 $shot2 -PassThru > $auditReportOutput
Compare-Object $shot2 $shot3 -PassTHru > $auditReportRemoteOutput
$auditCompare = Get-ChildItem $auditReportOutput
$auditRemoteCompare = Get-ChildItem $auditReportRemoteOutput
if ($auditCompare.Length -gt 0) {
$content = Get-ChildItem -Recurse $auditReportOutput
Add-Content $auditMismatchReport $content
Write-Host "Mismatch FOUND: " $sourceFolderName
$mismatchCount = $mismatchCount + 1
}
if ($auditRemoteCompare.Length -gt 0) {
$remoteContent = Get-ChilItem -Recurse $auditReportRemoteOutput
Add-Content $auditMismatchReport $remoteContent
Write-Host "Remote Mismatch FOUND: " $sourceFolderName
$remoteMismatchCount = $remoteMismatchCount + 1
}
}
send-mailmessage -from $emailFrom -to $emailTo -subject "AUDIT REPORT: Backups" -body "The full mismatch report is attached. There were $mismatchCount mismatched folders found and $remoteMismatchCount remote mismatched folders found. Please review to ensure backups are current." -Attachments "$auditMismatchReport" -priority High -dno onSuccess, onFailure -smtpServer $emailServer
}
我在交互式运行时发现的是,我将获得“当前正在处理FolderName”,如果该对象“太大”(无论是什么),脚本将只是坐在那里,不给任何错误的指示,但它不会继续(我等了几个小时)。有时我可以交互式地按Ctrl-C而不是退出脚本,它会将中断作为当前进程的取消并移动到下一个项目。
问题是,我需要每天安排这个以确保备份保持同步。任何帮助或见解表示赞赏。并且,是的,这可能是原始的和不优雅的,但现在我只是想解决我如何解决挂在我身上的脚本。
答案 0 :(得分:1)
不确定您使用的PS版本,但Get-Childitem已知存在扩展到大型目录的问题:
http://blogs.msdn.com/b/powershell/archive/2009/11/04/why-is-get-childitem-so-slow.aspx
如果您只是比较文件名,则可以使用legacy dir命令在大型目录结构中获得更好的结果。 / b(裸)开关只返回可以与Powershell的比较运算符一起使用的全名字符串。
$sourcedir = 'c:\testfiles'
$source_regex = [regex]::escape($sourcedir)
(cmd /c dir $Sourcedir /b /s) -replace "$source_regex\\(.+)$",'$1'
这使用正则表达式和-replace运算符来修剪dir返回的全名的soruce目录。 -replace运算符将使用数组,因此您可以在没有foreach循环的情况下在一个操作中完成所有这些操作。