私は現在、ビルドステップの一部としてTeamCityで使用されるPowerShellスクリプトに取り組んでいます。スクリプトは次のことを行う必要があります。
私はPowerShellスクリプトにまったく慣れていませんが、これまでのところ、期待どおりの動作をするものを作成しました。
Write-Host "Start checking for Unicorn serialization errors."
$files = get-childitem "%system.teamcity.build.workingDir%\Sitecore\serialization" -recurse -include *.item | where {! $_.PSIsContainer} | % { $_.FullName }
$arrayOfItemIds = @()
$NrOfFiles = $files.Length
[bool] $FoundDuplicates = 0
Write-Host "There are $NrOfFiles Unicorn item files to check."
foreach ($file in $files)
{
$thirdLineOfFile = (Get-Content $file)[2 .. 2]
if ($arrayOfItemIds -contains $thirdLineOfFile)
{
$FoundDuplicates = 1
$itemId = $thirdLineOfFile.Split(":")[1].Trim()
Write-Host "Duplicate item ID found!"
Write-Host "Item file path: $file"
Write-Host "Detected duplicate ID: $itemId"
Write-Host "-------------"
Write-Host ""
}
else
{
$arrayOfItemIds += $thirdLineOfFile
}
}
if ($foundDuplicates)
{
"##teamcity[buildStatus status='FAILURE' text='One or more duplicate ID's were detected in Sitecore serialised items. Check the build log to see which files and ID's are involved.']"
exit 1
}
Write-Host "End script checking for Unicorn serialization errors."
問題は:それは非常に遅いです!このスクリプトでチェックする必要のあるフォルダーには、現在14.000を超える.item-filesが含まれており、その量は今後も増え続ける可能性があります。非常に多くのファイルを開いて読み取ることは大規模な操作であることを理解していますが、完了するまでに約30分かかるとは思っていませんでした。これは、すべての(スナップショット)ビルドのビルド時間が30分長くなることを意味するため、長すぎます。これは許容できません。スクリプトが最大で数分で完了することを望んでいました。
これを行うためのより速いアプローチがないことを私はおそらく信じることができません..したがって、この分野での助けは大歓迎です!
解決
さて、私がこれまでに受け取った3つの答えすべてが、これで私を助けてくれたと言わなければなりません。私は最初に.NETFrameworkクラスを直接使用することから始め、次に辞書も使用して増大する配列の問題を解決しました。自分のスクリプトを実行するのにかかった時間は約30分でしたが、.NETFrameworkクラスを使用するとわずか2分に短縮されました。辞書ソリューションを使用した後も、わずか6秒または7秒になりました。私が使用する最後のスクリプト:
Write-Host "Start checking for Unicorn serialization errors."
[String[]] $allFilePaths = [System.IO.Directory]::GetFiles("%system.teamcity.build.workingDir%\Sitecore\serialization", "*.item", "AllDirectories")
$IdsProcessed = New-Object 'system.collections.generic.dictionary[string,string]'
[bool] $FoundDuplicates = 0
$NrOfFiles = $allFilePaths.Length
Write-Host "There are $NrOfFiles Unicorn item files to check."
Write-Host ""
foreach ($filePath in $allFilePaths)
{
[System.IO.StreamReader] $sr = [System.IO.File]::OpenText($filePath)
$unused1 = $sr.ReadLine() #read the first unused line
$unused2 = $sr.ReadLine() #read the second unused line
[string]$thirdLineOfFile = $sr.ReadLine()
$sr.Close()
if ($IdsProcessed.ContainsKey($thirdLineOfFile))
{
$FoundDuplicates = 1
$itemId = $thirdLineOfFile.Split(":")[1].Trim()
$otherFileWithSameId = $IdsProcessed[$thirdLineOfFile]
Write-Host "---------------"
Write-Host "Duplicate item ID found!"
Write-Host "Detected duplicate ID: $itemId"
Write-Host "Item file path 1: $filePath"
Write-Host "Item file path 2: $otherFileWithSameId"
Write-Host "---------------"
Write-Host ""
}
else
{
$IdsProcessed.Add($thirdLineOfFile, $filePath)
}
}
if ($foundDuplicates)
{
"##teamcity[buildStatus status='FAILURE' text='One or more duplicate ID|'s were detected in Sitecore serialised items. Check the build log to see which files and ID|'s are involved.']"
exit 1
}
Write-Host "End script checking for Unicorn serialization errors. No duplicate ID's were found."
みんなありがとう!
Get-ChildItemやGet-Contentなどの高レベルのコマンドを使用した場合にPowerShellが正確に何を行うかは明確ではありません。したがって、私はそれについてより明確にし、.NETフレームワーククラスを直接使用します。
を使用してフォルダ内のファイルのパスを取得します
[String[]] $files = [System.IO.Directory]::GetFiles($folderPath, "*.yourext")
次に、Get-Contentを使用するのではなく、各ファイルを開いて最初の3行を読み取ります。そのようです:
[System.IO.StreamReader] $sr = [System.IO.File]::OpenText(path)
[String]$line = $sr.ReadLine()
while ($line -ne $null)
{
# do your thing, break when you know enough
# ...
[String]$line = $sr.ReadLine()
}
$sr.Close()
私は1つか2つの間違いを犯したかもしれません、私はあまりにも怠惰に立ち上がってPCでこれをテストします。
また、使用するファイルが少なくなるようにビルドシステムを再設計することを検討することをお勧めします。14000ファイルと成長は不要のようです。一部のデータをより少ないファイルに統合できる場合は、パフォーマンスにも大いに役立つ可能性があります。
重複するGUIDをチェックするには、ファイル名を文字列として、Dictionary <Guid、String>クラスを使用します。次に、重複が見つかった場合は、どこに重複があるかを報告できます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加