Capture-MclCache: robocopy to Z: and verify by hash instead of zipping
This commit is contained in:
@@ -19,11 +19,16 @@
|
||||
files\ copies of the small text files (*.json, *.xml,
|
||||
*.tag, *.txt, *.ini, *.log, *.cmd, *.ps1, *.bat)
|
||||
under 5 MB, same relative paths
|
||||
mcl-capture-<label>-<timestamp>.zip
|
||||
SHA256SUMS hash of every file above, for checking the copy
|
||||
|
||||
Then it robocopies that folder to -CopyTo (default Z:\mcl-capture, the
|
||||
dev box pxe-images share), hashes every copied file back through the
|
||||
share and compares with SHA256SUMS. No zip: archives arrive empty on
|
||||
that share. The dev box can re-check with: sha256sum -c SHA256SUMS
|
||||
|
||||
Nothing large is copied: no WIM, driver, MSU or installer. Text copies
|
||||
have any Azure SAS signature (sig=...) blanked, so the zip carries no
|
||||
storage credential. Read-only on the cache; needs no admin rights.
|
||||
have any Azure SAS signature (sig=...) blanked, so the capture carries
|
||||
no storage credential. Read-only on the cache; needs no admin rights.
|
||||
|
||||
.PARAMETER Label
|
||||
Short name for this run, for example pro or ltsc.
|
||||
@@ -34,11 +39,16 @@
|
||||
.PARAMETER OutDir
|
||||
Where to write the capture. Default: the current user's Desktop, or
|
||||
this script's folder when there is no Desktop.
|
||||
|
||||
.PARAMETER CopyTo
|
||||
Folder to copy the capture into and verify. Default Z:\mcl-capture.
|
||||
Pass -CopyTo none to keep it on this PC only.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory = $true)][ValidatePattern('^[A-Za-z0-9_-]{1,20}$')][string]$Label,
|
||||
[string]$Root = "C:\ProgramData\GEAerospace\MediaCreator",
|
||||
[string]$OutDir = [Environment]::GetFolderPath("Desktop")
|
||||
[string]$OutDir = [Environment]::GetFolderPath("Desktop"),
|
||||
[string]$CopyTo = "Z:\mcl-capture"
|
||||
)
|
||||
$ErrorActionPreference = "Stop"
|
||||
if (-not $OutDir) { $OutDir = $PSScriptRoot } # no Desktop (e.g. run as SYSTEM)
|
||||
@@ -146,8 +156,13 @@ if ($skippedBig.Count) {
|
||||
}
|
||||
$sum | Set-Content -LiteralPath (Join-Path $dest "summary.txt") -Encoding UTF8
|
||||
|
||||
$zip = "$dest.zip"
|
||||
Compress-Archive -Path (Join-Path $dest "*") -DestinationPath $zip -Force
|
||||
# Relative path with forward slashes, the way sha256sum -c reads it.
|
||||
function Get-RelPath($full, $base) { $full.Substring($base.Length + 1).Replace('\', '/') }
|
||||
|
||||
$sumLines = foreach ($f in (Get-ChildItem -LiteralPath $dest -Recurse -File | Sort-Object FullName)) {
|
||||
"$((Get-FileHash -LiteralPath $f.FullName -Algorithm SHA256).Hash.ToLower()) $(Get-RelPath $f.FullName $dest)"
|
||||
}
|
||||
[System.IO.File]::WriteAllText((Join-Path $dest "SHA256SUMS"), (($sumLines -join "`n") + "`n"))
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Captured $($all.Count) files ($copied text files copied)." -ForegroundColor Green
|
||||
@@ -157,4 +172,45 @@ if ($tags.Count -eq 0) {
|
||||
if ($unreadable.Count) {
|
||||
Write-Host "$($unreadable.Count) file(s) could not be read; listed in summary.txt." -ForegroundColor Yellow
|
||||
}
|
||||
Write-Host "Send back: $zip"
|
||||
Write-Host "Capture folder: $dest"
|
||||
|
||||
if (-not $CopyTo -or $CopyTo -eq "none") { exit 0 }
|
||||
$drive = Split-Path -Qualifier $CopyTo -ErrorAction SilentlyContinue
|
||||
if (($drive -and -not (Test-Path -LiteralPath "$drive\")) -or -not (Test-Path -LiteralPath (Split-Path $CopyTo -Parent))) {
|
||||
Write-Host ""
|
||||
Write-Host "$CopyTo is not reachable, so nothing was copied." -ForegroundColor Yellow
|
||||
Write-Host "Map Z: to the dev box pxe-images share and run again, or copy the folder above by hand."
|
||||
exit 1
|
||||
}
|
||||
|
||||
$target = Join-Path $CopyTo (Split-Path $dest -Leaf)
|
||||
Write-Host ""
|
||||
Write-Host "Copying to $target ..."
|
||||
& robocopy.exe $dest $target /E /COPY:DT /R:2 /W:5 /NP /NFL /NDL /NJH /NJS | Out-Null
|
||||
$rc = $LASTEXITCODE
|
||||
if ($rc -ge 8) {
|
||||
Write-Host "Copy FAILED (robocopy exit $rc)." -ForegroundColor Red
|
||||
exit 2
|
||||
}
|
||||
|
||||
# Read every file back through the share and compare with SHA256SUMS.
|
||||
$bad = New-Object System.Collections.Generic.List[string]
|
||||
foreach ($line in $sumLines) {
|
||||
$hash = $line.Substring(0, 64)
|
||||
$rel = $line.Substring(66)
|
||||
$copy = Join-Path $target ($rel.Replace('/', '\'))
|
||||
if (-not (Test-Path -LiteralPath $copy -PathType Leaf)) { $bad.Add("missing $rel"); continue }
|
||||
$got = (Get-FileHash -LiteralPath $copy -Algorithm SHA256).Hash.ToLower()
|
||||
if ($got -ne $hash) { $bad.Add("differs $rel ($((Get-Item -LiteralPath $copy).Length) bytes)") }
|
||||
}
|
||||
if ((Get-FileHash -LiteralPath (Join-Path $target "SHA256SUMS") -Algorithm SHA256).Hash -ne
|
||||
(Get-FileHash -LiteralPath (Join-Path $dest "SHA256SUMS") -Algorithm SHA256).Hash) {
|
||||
$bad.Add("differs SHA256SUMS")
|
||||
}
|
||||
if ($bad.Count) {
|
||||
Write-Host "Copy NOT verified: $($bad.Count) of $($sumLines.Count + 1) files wrong." -ForegroundColor Red
|
||||
foreach ($b in $bad) { Write-Host " $b" }
|
||||
exit 2
|
||||
}
|
||||
Write-Host "Copied and verified: all $($sumLines.Count + 1) files match." -ForegroundColor Green
|
||||
Write-Host "On the share: $target"
|
||||
|
||||
Reference in New Issue
Block a user