我有一个有效的PowerShell脚本,可以在数千个文件中查找和替换一些带有新字符串的不同字符串,而无需更改文件的修改日期。在任何给定的文件中,可能有数百个要替换的字符串实例。文件本身并不是很大,可能只有1-50MB(我正在测试的目录快速浏览显示最大的~33MB)。
我在具有4个vCPU和4GB RAM的Server 2012 R2 VM中运行脚本。我已将Powershell的MaxMemoryPerShellMB值设置为3GB。如前所述,该脚本可以工作,但2-4小时后,powershell将开始抛出OutOfMemoryExceptions并崩溃。该脚本是V2友好的'而我还没有将它用于V3 +,但我怀疑这太重要了。
我的问题是是否可以改进脚本以防止/消除我目前遇到的内存异常。如果它运行得慢,我不介意,只要它能完成工作而不必每隔几小时检查一次并重新启动它。
$i=0
$all = Get-ChildItem -Recurse -Include *.txt
$scriptfiles = Select-String -Pattern string1,string2,string3 $all
$output = "C:\Temp\scriptoutput.txt"
foreach ($file in $scriptFiles)
{
$filecreate=(Get-ChildItem $file.Path).creationtime
$fileaccess=(Get-ChildItem $file.Path).lastaccesstime
$filewrite=(Get-ChildItem $file.Path).lastwritetime
"$file.Path,Created: $filecreate,Accessed: $fileaccess,Modified: $filewrite" | out-file -FilePath $output -Append
(Get-Content $file.Path) | ForEach-Object {$_ -replace "string1", "newstring" `
-replace "string2", "newstring" `
-replace "string3", "newstring"
} | Set-Content $file.Path
(Get-ChildItem $file.Path).creationtime=$filecreate
(Get-ChildItem $file.Path).lastaccesstime=$fileaccess
(Get-ChildItem $file.Path).lastwritetime=$filewrite
$filecreate=(Get-ChildItem $file.Path).creationtime
$fileaccess=(Get-ChildItem $file.Path).lastaccesstime
$filewrite=(Get-ChildItem $file.Path).lastwritetime
"$file.Path,UPDATED Created: $filecreate,UPDATED Accessed: $fileaccess,UPDATED Modified: $filewrite" | out-file -FilePath $output -Append
$i++}
欢迎任何评论,批评和建议。
由于
答案 0 :(得分:0)
我可以看到的最大问题是您反复获取要查询的每个属性的文件。用每个循环传递一次调用替换它并保存它以在传递期间使用。 Out-File也是将数据输出到文件的较慢方法之一。
$output = "C:\Temp\scriptoutput.txt"
$scriptfiles = Get-ChildItem -Recurse -Include *.txt |
Select-String -Pattern string1,string2,string3 |
Select-Object -ExpandProperty Path
$scriptfiles | ForEach-Object{
$file = Get-Item $_
# Save currrent file times
$filecreate=$file.creationtime
$fileaccess=$file.lastaccesstime
$filewrite=$file.lastwritetime
"$file,Created: $filecreate,Accessed: $fileaccess,Modified: $filewrite"
# Update content.
(Get-Content $file) -replace "string1", "newstring" `
-replace "string2", "newstring" `
-replace "string3", "newstring" | Set-Content $file
# Write all the original times back.
$file.creationtime=$filecreate
$file.lastaccesstime=$fileaccess
$file.lastwritetime=$filewrite
# Verify the changes... Should not be required but it is what you were doing.
$filecreate=$file.creationtime
$fileaccess=$file.lastaccesstime
$filewrite=$file.lastwritetime
"$file,UPDATED Created: $filecreate,UPDATED Accessed: $fileaccess,UPDATED Modified: $filewrite"
} | Set-Content $output
未经测试但应该没问题。
根据你的替换实际上你可能会节省一些时间。在生产运行之前先进行测试。
我删除了你所拥有的计数器,因为它在代码中没有出现。
您的日志记录可以很容易地基于csv,因为您已准备好所有对象,但我只是想确保在我们前往远程之前我们是正确的轨道。