由于大对象,Get-ChildItem脚本挂起?

时间:2013-11-15 20:21:19

标签: powershell powershell-v2.0

好的 - 我是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而不是退出脚本,它会将中断作为当前进程的取消并移动到下一个项目。

问题是,我需要每天安排这个以确保备份保持同步。任何帮助或见解表示赞赏。并且,是的,这可能是原始的和不优雅的,但现在我只是想解决我如何解决挂在我身上的脚本。

1 个答案:

答案 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循环的情况下在一个操作中完成所有这些操作。