我一直在摆弄一个脚本(由Vidrine编写,来自http://jfrmilner.rdpress.com/),它编目了文件服务器的NTFS权限。目前,它会查看整个服务器共享,并仅从文件夹中收集权限并忽略文件。它将数据存储在对象中,并将其写入阵列列表,稍后将其转储到CSV中。作为参考,文件服务器相当大,其中有大约7.4TB的数据。最初我调用了一个数组并使用+ =运算符写入它,但是.net处理数组使得在中等大小的子目录上运行它是一个非常重的内存事件。
我遇到的问题是该脚本完全占用内存,我无法分辨这是否仅仅是因为脚本是如何编写的,还是在将它们写入arraylist之后它是否保留在对象上。例如,当我针对特定的子目录而不是整个服务器运行脚本时,脚本将使用大约1.4GB的RAM并生成一个148MB(100,000行×3列)的CSV。我正在运行它的机器有16GB的RAM,它仍然设法在对整个目录运行时出现问题。
我已经玩弄[void]试图在写入$ arrResults后从内存中消除$ objResults,但我似乎不明白void cast是如何工作的。我也尝试使用[System.GC] :: Collect()函数,但它只是减慢了循环和内存的积累,但没有帮助(这似乎也是一种讨厌的做法)
我尝试在Powershell V5(也是V1,V2和V4)ISE中直接从命令行运行它。
$ objResults被添加到$ arrResults后是否会留在内存中并且可以修复吗?或者arraylist实际上是否达到了15GB的大小? 我对Powershell FYI很新。
Import-module ActiveDirectory
$targetServer = 'S:\shared data\' #Enter hostname
$targetDirectory = '' #Enter directory name
$target = Join-Path -ChildPath $targetDirectory -Path $targetServer
$arrResults = New-ObjectSystem.Collections.Generic.List[System.Object]
$exportPath = 'C:\temp\NTFS-OUTPUT.csv' #Enter name of the CSV output file
#Query target directory for all 'folders' (excludes files via Where statement)
Get-ChildItem -Recurse -Path $target | Where { $_.PSIsContainer} |
forEach {
$objPath = $_.FullName
$coLACL = Get-Acl -Path $objPath
forEach ( $objACL in $colACL ) {
forEach ( $accessRight in $objACL.Access ) {
$objResults = New-Object –TypeName PSObject
$objResults | Add-Member –MemberType NoteProperty –Name DirectoryPath –Value $objPath
$objResults | Add-Member –MemberType NoteProperty –Name Identity –Value $accessRight.IdentityReference
$objResults | Add-Member –MemberType NoteProperty –Name SystemRights –Value $accessRight.FileSystemRights
#$objResults | Add-Member –MemberType NoteProperty –Name SystemRightsType –Value $accessRight.AccessControlType
#$objResults | Add-Member -MemberType NoteProperty -Name IsInherited -Value $accessRight.IsInherited
#$objResults | Add-Member -MemberType NoteProperty -Name InheritanceFlags -Value $accessRight.InheritanceFlags
#$objResults | Add-Member –MemberType NoteProperty –Name RulesProtected –Value $objACL.AreAccessRulesProtected
$arrResults.Add($objResults)
}
}
}
$arrResults | Export-CSV -NoTypeInformation -Path $exportPath
答案 0 :(得分:3)
不需要中间数组:只需输出值并将管道扩展到Export-Csv。
Add-Member非常慢,特别是在通过管道多次调用时
在PowerShell 3.0及更高版本中,您可以使用[PSCustomObject]
加速器作为文字哈希表。
Get-ChildItem -Recurse -Path $target -Directory | ForEach {
foreach ($objACL in (Get-Acl -Path $_.FullName)) {
foreach ($accessRight in $objACL.Access ) {
[PSCustomObject]@{
DirectoryPath = $_.FullName
Identity = $accessRight.IdentityReference
SystemRights = $accessRight.FileSystemRights
}
}
}
} | Export-CSV -NoTypeInformation -Path $exportPath