Rename phy-z-srv-gpu01 to phy-srv-gpu01; fix share analysis scripts
- rename host/group/folder everywhere to match the server's actual hostname and physical label - share-analysis.ps1: sanitize the output filename prefix — '-Paths "D:"' produced 'D:-file-types.csv' and Export-Csv failed with 'path format not supported', so no CSVs were written - share-analysis.ps1: new -FolderDepth so folders can be aggregated at D:\Abteilungen\<Share> level, which matches the share layout - list-shares.ps1: -WithSize walks local paths instead of UNC when run on the server itself (UNC was orders of magnitude slower and looked stuck) and prints progress every 50k files Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Lists all SMB shares of a Windows file server incl. local path, size and
|
||||
permissions — the basis for the include/exclude decision (projektplan §2.6).
|
||||
|
||||
.DESCRIPTION
|
||||
Run ON the file server (or against a remote one via -ComputerName). Reports
|
||||
per share: name, local path, description, share-level permissions, NTFS
|
||||
groups, plus optional size/file count. Admin shares (C$, ADMIN$, IPC$) are
|
||||
skipped unless -IncludeAdminShares is given.
|
||||
|
||||
Purely read-only. Requires local admin for Get-SmbShare (part of Windows
|
||||
Server, no extra module needed).
|
||||
|
||||
.EXAMPLE
|
||||
.\list-shares.ps1
|
||||
|
||||
.EXAMPLE
|
||||
# with size per share — run this ON the file server, it then walks the local
|
||||
# paths instead of the UNC paths (far faster). Still minutes to hours on
|
||||
# millions of files; progress is printed every 50k files.
|
||||
.\list-shares.ps1 -WithSize
|
||||
|
||||
.NOTES
|
||||
Faster alternative when all shares live under one drive (as on Z-FILESERVER,
|
||||
where everything sits under D:): run share-analysis.ps1 once with a matching
|
||||
folder depth instead of measuring every share separately, e.g.
|
||||
|
||||
.\share-analysis.ps1 -Paths "D:" -FolderDepth 2
|
||||
|
||||
That produces size/count per D:\Abteilungen\<Share> in a single pass over
|
||||
the disk, which is what the share list here maps onto.
|
||||
#>
|
||||
param(
|
||||
[string]$ComputerName = $env:COMPUTERNAME,
|
||||
[switch]$IncludeAdminShares,
|
||||
[switch]$WithSize,
|
||||
[string]$OutDir = (Join-Path (Get-Location) "share-list")
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Continue'
|
||||
New-Item -ItemType Directory -Path $OutDir -Force | Out-Null
|
||||
|
||||
Write-Host "=== SMB shares on $ComputerName ===" -ForegroundColor Cyan
|
||||
|
||||
$shares = Get-SmbShare -CimSession $ComputerName -ErrorAction Stop
|
||||
if (-not $IncludeAdminShares) {
|
||||
$shares = $shares | Where-Object { -not $_.Name.EndsWith('$') }
|
||||
}
|
||||
|
||||
$result = foreach ($sh in $shares) {
|
||||
Write-Host (" {0,-25} {1}" -f $sh.Name, $sh.Path)
|
||||
|
||||
# share-level permissions
|
||||
$sharePerms = try {
|
||||
(Get-SmbShareAccess -Name $sh.Name -CimSession $ComputerName -ErrorAction Stop |
|
||||
ForEach-Object { "$($_.AccountName)=$($_.AccessRight)" }) -join '; '
|
||||
} catch { 'n/a' }
|
||||
|
||||
# NTFS permissions (top level only) — who actually has access
|
||||
$ntfsPerms = try {
|
||||
$uncPath = "\\$ComputerName\$($sh.Name)"
|
||||
((Get-Acl -LiteralPath $uncPath -ErrorAction Stop).Access |
|
||||
ForEach-Object { "$($_.IdentityReference)=$($_.FileSystemRights)" } |
|
||||
Select-Object -Unique | Select-Object -First 10) -join '; '
|
||||
} catch { 'n/a' }
|
||||
|
||||
$sizeGB = $null; $fileCount = $null
|
||||
if ($WithSize) {
|
||||
# Walk the LOCAL path when we are on the server itself — going through
|
||||
# the UNC path (\\server\share) routes every single file through the SMB
|
||||
# stack and is slower by orders of magnitude on large shares.
|
||||
$scanPath = if ($ComputerName -eq $env:COMPUTERNAME -and $sh.Path) {
|
||||
$sh.Path
|
||||
} else {
|
||||
"\\$ComputerName\$($sh.Name)"
|
||||
}
|
||||
|
||||
$sw = [System.Diagnostics.Stopwatch]::StartNew()
|
||||
$n = 0L; $bytes = 0L
|
||||
Get-ChildItem -LiteralPath $scanPath -Recurse -File -Force -ErrorAction SilentlyContinue |
|
||||
ForEach-Object {
|
||||
$n++; $bytes += $_.Length
|
||||
if ($n % 50000 -eq 0) {
|
||||
Write-Host (" ... {0:N0} files, {1:N1} GB ({2:N0}s)" -f $n, ($bytes / 1GB), $sw.Elapsed.TotalSeconds) -ForegroundColor DarkGray
|
||||
}
|
||||
}
|
||||
$sw.Stop()
|
||||
$sizeGB = [Math]::Round($bytes / 1GB, 2)
|
||||
$fileCount = $n
|
||||
Write-Host (" {0:N0} files, {1:N1} GB in {2:N0}s" -f $n, ($bytes / 1GB), $sw.Elapsed.TotalSeconds) -ForegroundColor DarkGray
|
||||
}
|
||||
|
||||
[PSCustomObject]@{
|
||||
Name = $sh.Name
|
||||
Path = $sh.Path
|
||||
Description = $sh.Description
|
||||
SharePermissions = $sharePerms
|
||||
NtfsPermissions = $ntfsPerms
|
||||
SizeGB = $sizeGB
|
||||
FileCount = $fileCount
|
||||
}
|
||||
}
|
||||
|
||||
$csv = Join-Path $OutDir "smb-shares.csv"
|
||||
$result | Export-Csv $csv -NoTypeInformation -Encoding UTF8
|
||||
$result | Format-Table Name, Path, SizeGB, FileCount -AutoSize
|
||||
|
||||
# DFS namespaces (if used) — often the path users actually see
|
||||
Write-Host "`n=== DFS namespaces ===" -ForegroundColor Cyan
|
||||
try {
|
||||
$roots = Get-DfsnRoot -ErrorAction Stop
|
||||
if ($roots) {
|
||||
$dfs = foreach ($r in $roots) {
|
||||
Get-DfsnFolder -Path "$($r.Path)\*" -ErrorAction SilentlyContinue | ForEach-Object {
|
||||
$t = Get-DfsnFolderTarget -Path $_.Path -ErrorAction SilentlyContinue
|
||||
[PSCustomObject]@{ DfsPath = $_.Path; Targets = ($t.TargetPath -join '; ') }
|
||||
}
|
||||
}
|
||||
$dfs | Export-Csv (Join-Path $OutDir "dfs-namespaces.csv") -NoTypeInformation -Encoding UTF8
|
||||
$dfs | Format-Table -AutoSize
|
||||
} else { Write-Host " none" }
|
||||
} catch {
|
||||
Write-Host " no DFS role / not available on this host"
|
||||
}
|
||||
|
||||
Write-Host "`nResults in: $OutDir" -ForegroundColor Green
|
||||
Reference in New Issue
Block a user