162 lines
6.6 KiB
PowerShell
162 lines
6.6 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Collects DayZ server + client logs (and the mod's live config) for
|
|
debugging the YALootBoxes mod, then bundles them into one timestamped
|
|
.zip that is easy to hand off.
|
|
|
|
.DESCRIPTION
|
|
Copies recent .RPT / .ADM / .log / .mdmp / crash logs from the server
|
|
profile folder and the client log folder, plus the auto-generated
|
|
profiles\YALootBoxes\*.json config. Produces:
|
|
- server\ , client\ : the raw collected files
|
|
- server\YALootBoxes_config\*.json: the mod's live config
|
|
- YALootBoxes_filtered.txt : every "[YALootBoxes]" line, by file
|
|
- summary.txt : machine info + ERROR/WARN counts + file list
|
|
...all inside YALootBoxes_logs_<timestamp>.zip on your Desktop.
|
|
|
|
Handles files locked by a running server (shared-read copy).
|
|
|
|
.EXAMPLE
|
|
powershell -ExecutionPolicy Bypass -File .\Collect-YALootBoxesLogs.ps1
|
|
|
|
.EXAMPLE
|
|
# widen the window to the last 48 hours
|
|
powershell -ExecutionPolicy Bypass -File .\Collect-YALootBoxesLogs.ps1 -SinceHours 48
|
|
#>
|
|
[CmdletBinding()]
|
|
param(
|
|
[string]$ServerProfile = 'C:\Program Files (x86)\Steam\steamapps\common\DayZServer\profiles',
|
|
[string]$ClientLogs = 'C:\Users\drasi\AppData\Local\DayZ',
|
|
[string]$OutDir = "$env:USERPROFILE\Desktop",
|
|
[int] $SinceHours = 12,
|
|
[string]$Tag = '[YALootBoxes]'
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
$stamp = Get-Date -Format 'yyyyMMdd_HHmmss'
|
|
$stageRoot = Join-Path $env:TEMP "YALB_logs_$stamp"
|
|
$stageServer = Join-Path $stageRoot 'server'
|
|
$stageClient = Join-Path $stageRoot 'client'
|
|
New-Item -ItemType Directory -Force -Path $stageServer, $stageClient | Out-Null
|
|
|
|
$patterns = '*.RPT', '*.log', '*.ADM', '*.mdmp', 'crash_*.log', 'error.log', 'script*.log'
|
|
$cutoff = (Get-Date).AddHours(-$SinceHours)
|
|
|
|
# Copy a file even if a running server holds it open (shared read).
|
|
function Copy-Locked {
|
|
param([string]$Src, [string]$Dst)
|
|
try {
|
|
$in = [System.IO.File]::Open($Src, 'Open', 'Read', 'ReadWrite')
|
|
try {
|
|
$out = [System.IO.File]::Create($Dst)
|
|
try { $in.CopyTo($out) } finally { $out.Dispose() }
|
|
} finally { $in.Dispose() }
|
|
return $true
|
|
} catch {
|
|
Write-Warning "Could not copy '$Src': $($_.Exception.Message)"
|
|
return $false
|
|
}
|
|
}
|
|
|
|
function Collect {
|
|
param([string]$Source, [string]$Stage, [string]$Label)
|
|
if (-not (Test-Path $Source)) {
|
|
Write-Warning "$Label path not found: $Source"
|
|
return @()
|
|
}
|
|
$files = Get-ChildItem -Path $Source -Recurse -File -Include $patterns -ErrorAction SilentlyContinue |
|
|
Where-Object { $_.LastWriteTime -ge $cutoff }
|
|
|
|
# Always include the newest .RPT even if it predates the cutoff window.
|
|
if (-not ($files | Where-Object { $_.Extension -eq '.RPT' })) {
|
|
$newestRpt = Get-ChildItem -Path $Source -Recurse -File -Filter '*.RPT' -ErrorAction SilentlyContinue |
|
|
Sort-Object LastWriteTime -Descending | Select-Object -First 1
|
|
if ($newestRpt) { $files = @($files) + $newestRpt }
|
|
}
|
|
|
|
$collected = @()
|
|
foreach ($f in ($files | Sort-Object FullName -Unique)) {
|
|
$dst = Join-Path $Stage $f.Name
|
|
if (Test-Path $dst) {
|
|
$dst = Join-Path $Stage ('{0}_{1}{2}' -f $f.BaseName, $f.LastWriteTime.ToString('HHmmss'), $f.Extension)
|
|
}
|
|
if (Copy-Locked $f.FullName $dst) {
|
|
$collected += [pscustomobject]@{
|
|
Source = $Label; Name = $f.Name; Size = $f.Length; Modified = $f.LastWriteTime
|
|
}
|
|
}
|
|
}
|
|
return $collected
|
|
}
|
|
|
|
# --- collect server + client logs ---
|
|
$serverFiles = @(Collect -Source $ServerProfile -Stage $stageServer -Label 'server')
|
|
$clientFiles = @(Collect -Source $ClientLogs -Stage $stageClient -Label 'client')
|
|
|
|
# --- grab the mod's live generated config ($profile:YALootBoxes\*.json) ---
|
|
$modCfg = Join-Path $ServerProfile 'YALootBoxes'
|
|
if (Test-Path $modCfg) {
|
|
$cfgStage = Join-Path $stageServer 'YALootBoxes_config'
|
|
New-Item -ItemType Directory -Force -Path $cfgStage | Out-Null
|
|
Get-ChildItem $modCfg -Filter '*.json' -File -ErrorAction SilentlyContinue | ForEach-Object {
|
|
Copy-Locked $_.FullName (Join-Path $cfgStage $_.Name) | Out-Null
|
|
}
|
|
} else {
|
|
Write-Warning "Mod config folder not found (mod may not have run yet): $modCfg"
|
|
}
|
|
|
|
$all = $serverFiles + $clientFiles
|
|
|
|
# --- extract only the mod-tagged lines into one file ---
|
|
$filterPath = Join-Path $stageRoot 'YALootBoxes_filtered.txt'
|
|
$sb = New-Object System.Text.StringBuilder
|
|
$textFiles = Get-ChildItem -Path $stageServer, $stageClient -Recurse -File |
|
|
Where-Object { $_.Extension -in '.RPT', '.log', '.ADM' }
|
|
foreach ($tf in $textFiles) {
|
|
$hits = Select-String -Path $tf.FullName -SimpleMatch -Pattern $Tag -ErrorAction SilentlyContinue
|
|
if ($hits) {
|
|
[void]$sb.AppendLine("===== $($tf.Name) ($($hits.Count) line(s)) =====")
|
|
foreach ($h in $hits) { [void]$sb.AppendLine(('{0,6}: {1}' -f $h.LineNumber, $h.Line.Trim())) }
|
|
[void]$sb.AppendLine('')
|
|
}
|
|
}
|
|
if ($sb.Length -eq 0) { [void]$sb.AppendLine("No '$Tag' lines found in the collected logs.") }
|
|
Set-Content -Path $filterPath -Value $sb.ToString() -Encoding UTF8
|
|
|
|
# --- summary ---
|
|
$errCount = (Select-String -Path $filterPath -SimpleMatch -Pattern '[ERROR]' -ErrorAction SilentlyContinue).Count
|
|
$warnCount = (Select-String -Path $filterPath -SimpleMatch -Pattern '[WARN]' -ErrorAction SilentlyContinue).Count
|
|
|
|
$lines = @(
|
|
'YALootBoxes log bundle'
|
|
"Generated: $(Get-Date -Format 'u')"
|
|
"Machine: $env:COMPUTERNAME User: $env:USERNAME"
|
|
"Window: last $SinceHours hour(s) Tag: $Tag"
|
|
"Server src: $ServerProfile"
|
|
"Client src: $ClientLogs"
|
|
''
|
|
"Mod-tagged ERROR lines: $errCount"
|
|
"Mod-tagged WARN lines: $warnCount"
|
|
''
|
|
'Files collected:'
|
|
)
|
|
if ($all) {
|
|
foreach ($f in $all) {
|
|
$lines += (' [{0}] {1} ({2:N0} bytes, {3:yyyy-MM-dd HH:mm})' -f $f.Source, $f.Name, $f.Size, $f.Modified)
|
|
}
|
|
} else {
|
|
$lines += ' (none - check the paths or widen -SinceHours)'
|
|
}
|
|
Set-Content -Path (Join-Path $stageRoot 'summary.txt') -Value $lines -Encoding UTF8
|
|
|
|
# --- zip + cleanup ---
|
|
$zip = Join-Path $OutDir "YALootBoxes_logs_$stamp.zip"
|
|
if (Test-Path $zip) { Remove-Item $zip -Force }
|
|
Compress-Archive -Path (Join-Path $stageRoot '*') -DestinationPath $zip
|
|
Remove-Item $stageRoot -Recurse -Force
|
|
|
|
Write-Host ''
|
|
Write-Host "Collected $($all.Count) log file(s)." -ForegroundColor Green
|
|
Write-Host "Mod-tagged lines -> ERROR: $errCount WARN: $warnCount"
|
|
Write-Host "Bundle: $zip" -ForegroundColor Cyan
|
|
Write-Host 'Send me that .zip (summary.txt + YALootBoxes_filtered.txt inside are the key files).'
|