sync: auto-sync from HOWARD-HOME at 2026-06-21 12:25:00
Author: Howard Enos Machine: HOWARD-HOME Timestamp: 2026-06-21 12:25:00
This commit is contained in:
@@ -186,6 +186,83 @@ PS
|
||||
echo "[OK] uploaded $(basename "$remote") ($nch chunk(s)) -> $(echo "$r"|jq -r '.stdout'|tr -d '\r')"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# DETACHED, NO-CAP execution. A scanner must never be killed by an RMM command
|
||||
# timeout - large drives can scan for hours. So we launch GuruScan as a
|
||||
# scheduled task with ExecutionTimeLimit=0 (unlimited); the launch command
|
||||
# returns immediately, the scan runs to completion on its own, and we poll a
|
||||
# disk done-marker with NO overall cap.
|
||||
# ---------------------------------------------------------------------------
|
||||
# gs_launch_detached "<invoke-guruscan-args>" <tag>
|
||||
gs_launch_detached() {
|
||||
local gsargs="$1" tag="$2"
|
||||
local wl="$WORK_DIR/wrapper_$tag.ps1"
|
||||
cat > "$wl" <<PS
|
||||
\$ErrorActionPreference='Continue'
|
||||
\$marker='C:\\GuruScan\\_done_${tag}.txt'
|
||||
\$log='C:\\GuruScan\\_log_${tag}.txt'
|
||||
Remove-Item \$marker,\$log -Force -ErrorAction SilentlyContinue
|
||||
try { & C:\\GuruScan\\Invoke-GuruScan.ps1 ${gsargs} *> \$log; \$rc=\$LASTEXITCODE }
|
||||
catch { \$rc=-1; \$_ | Out-String | Add-Content \$log }
|
||||
"DONE rc=\$rc at \$(Get-Date -Format o)" | Set-Content \$marker
|
||||
PS
|
||||
upload_file "$wl" "C:\\GuruScan\\_detached_${tag}.ps1" || return 1
|
||||
local sf="$WORK_DIR/launch_$tag.ps1"
|
||||
cat > "$sf" <<PS
|
||||
\$ErrorActionPreference='Stop'
|
||||
\$tn='GuruScan-${tag}'
|
||||
try{ Unregister-ScheduledTask -TaskName \$tn -Confirm:\$false -ErrorAction SilentlyContinue }catch{}
|
||||
\$a=New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-NonInteractive -ExecutionPolicy Bypass -WindowStyle Hidden -File C:\\GuruScan\\_detached_${tag}.ps1'
|
||||
\$pr=New-ScheduledTaskPrincipal -UserId 'SYSTEM' -LogonType ServiceAccount -RunLevel Highest
|
||||
\$st=New-ScheduledTaskSettingsSet -ExecutionTimeLimit ([TimeSpan]::Zero) -StartWhenAvailable -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -MultipleInstances IgnoreNew
|
||||
Register-ScheduledTask -TaskName \$tn -Action \$a -Principal \$pr -Settings \$st -Force | Out-Null
|
||||
Start-ScheduledTask -TaskName \$tn
|
||||
Start-Sleep -Seconds 2
|
||||
Write-Output ('LAUNCHED ' + \$tn + ' state=' + ((Get-ScheduledTask -TaskName \$tn).State))
|
||||
PS
|
||||
run_ps "$sf" 90 24 "launch-$tag" || return 1
|
||||
}
|
||||
|
||||
# gs_wait_detached <tag> <label> -- polls for the done-marker; NO cap (24h safety net)
|
||||
gs_wait_detached() {
|
||||
local tag="$1" label="$2" i=0 maxi=2880
|
||||
local sf="$WORK_DIR/poll_$tag.ps1"
|
||||
cat > "$sf" <<PS
|
||||
\$ErrorActionPreference='Continue'
|
||||
\$marker='C:\\GuruScan\\_done_${tag}.txt'
|
||||
if(Test-Path \$marker){ Write-Output ('MARKER ' + ((Get-Content \$marker -Raw) -replace '\s+',' ').Trim()) }
|
||||
else {
|
||||
\$act=@(); foreach(\$n in @('a2cmd','HitmanPro_x64','rkill')){ \$p=Get-Process -Name \$n -ErrorAction SilentlyContinue; if(\$p){ \$act += (\$n+' CPU='+[math]::Round((\$p|Select-Object -First 1).CPU,0)+'s') } }
|
||||
if(\$act.Count){ Write-Output ('RUNNING ' + (\$act -join ', ')) } else { Write-Output 'RUNNING (between scanners / starting)' }
|
||||
}
|
||||
PS
|
||||
echo "[INFO] waiting for '$label' to finish (NO cap; checking every 30s)..."
|
||||
while [ $i -lt $maxi ]; do
|
||||
run_ps "$sf" 30 8 "poll-$tag" >/dev/null 2>&1 || true
|
||||
local out; out="$(jq -r '.stdout' "$WORK_DIR/last_result.json" 2>/dev/null | tr -d '\r')"
|
||||
if printf '%s' "$out" | grep -q '^MARKER '; then
|
||||
echo "[OK] '$label' finished -> $(printf '%s' "$out" | grep '^MARKER ')"
|
||||
return 0
|
||||
fi
|
||||
i=$((i+1))
|
||||
if [ $((i % 4)) -eq 0 ]; then echo " [$label] $((i/2)) min elapsed: $(printf '%s' "$out" | grep -E '^(RUNNING|MARKER)' | head -1)"; fi
|
||||
sleep 30
|
||||
done
|
||||
echo "[WARN] '$label' exceeded 24h safety net"; return 1
|
||||
}
|
||||
|
||||
# fetch the captured console log of a detached run (contains GURUSCAN_RESULT_JSON)
|
||||
gs_fetch_detached_log() {
|
||||
local tag="$1"
|
||||
local sf="$WORK_DIR/getlog_$tag.ps1"
|
||||
cat > "$sf" <<PS
|
||||
\$p='C:\\GuruScan\\_log_${tag}.txt'
|
||||
if(Test-Path \$p){ Get-Content \$p -Raw } else { Write-Output 'NO-LOG' }
|
||||
PS
|
||||
run_ps "$sf" 60 24 "fetchlog-$tag" >/dev/null 2>&1 || true
|
||||
jq -r '.stdout' "$WORK_DIR/last_result.json" 2>/dev/null
|
||||
}
|
||||
|
||||
# ===========================================================================
|
||||
phase_prep() {
|
||||
echo ""; echo "=== PHASE: prep ==="
|
||||
@@ -283,21 +360,14 @@ PS
|
||||
|
||||
# ===========================================================================
|
||||
phase_scan() {
|
||||
echo ""; echo "=== PHASE: scan (clean mode, full chain, headless - LONG) ==="
|
||||
local sf="$WORK_DIR/scan.ps1"
|
||||
cat > "$sf" <<'PS'
|
||||
$ErrorActionPreference='Continue'
|
||||
& C:\GuruScan\Invoke-GuruScan.ps1 -Headless
|
||||
PS
|
||||
# Emsisoft timeout_min=120, HitmanPro=60. Give the command 2.5h and poll up to 3h.
|
||||
run_ps "$sf" 9000 2160 "guruscan-run" || { _logerr "GuruScan run failed" --context "host=$AGENT_HOST"; echo "[ERROR] scan phase failed"; return 1; }
|
||||
# surface the structured result line
|
||||
local out; out="$(jq -r '.stdout' "$WORK_DIR/last_result.json" 2>/dev/null)"
|
||||
echo ""; echo "=== PHASE: scan (clean mode, full chain, headless, DETACHED - NO CAP) ==="
|
||||
gs_launch_detached "-Headless" "scan" || { _logerr "detached scan launch failed" --context "host=$AGENT_HOST"; echo "[ERROR] launch failed"; return 1; }
|
||||
gs_wait_detached "scan" "full-scan" || true
|
||||
local out; out="$(gs_fetch_detached_log "scan")"
|
||||
echo ""
|
||||
echo "$out" | grep 'GURUSCAN_RESULT_JSON:' | sed 's/^GURUSCAN_RESULT_JSON://' | jq '.' 2>/dev/null \
|
||||
|| echo "[WARN] no GURUSCAN_RESULT_JSON line in stdout (see full output above)"
|
||||
local cmd_id; cmd_id="$(cat "$WORK_DIR/last_cmd_id" 2>/dev/null||echo ?)"
|
||||
post_alert "[RMM] GuruScan test: scan finished on $AGENT_HOST -> cmd:${cmd_id:0:8}"
|
||||
printf '%s\n' "$out" | grep 'GURUSCAN_RESULT_JSON:' | sed 's/^.*GURUSCAN_RESULT_JSON://' | jq '.' 2>/dev/null \
|
||||
|| echo "[WARN] no GURUSCAN_RESULT_JSON in detached log"
|
||||
post_alert "[RMM] GuruScan test: detached scan finished on $AGENT_HOST"
|
||||
}
|
||||
|
||||
# ===========================================================================
|
||||
@@ -412,12 +482,10 @@ PS
|
||||
ve_seed_ps > "$WORK_DIR/ve_seed.ps1"
|
||||
run_ps "$WORK_DIR/ve_seed.ps1" 60 24 "seed-for-$eng" || { echo "[ERROR] seed failed for $eng"; return 1; }
|
||||
|
||||
# 2) run ONLY this engine in clean mode (long; Emsisoft updates+scans C:\)
|
||||
cat > "$WORK_DIR/ve_run.ps1" <<PS
|
||||
\$ErrorActionPreference='Continue'
|
||||
& C:\\GuruScan\\Invoke-GuruScan.ps1 -Scanners $eng -Headless
|
||||
PS
|
||||
run_ps "$WORK_DIR/ve_run.ps1" 2700 600 "run-$eng" || echo "[WARN] $eng run reported non-zero"
|
||||
# 2) run ONLY this engine in clean mode, DETACHED with NO cap (Emsisoft
|
||||
# updates+scans all of C:\ - can take far longer than any RMM timeout)
|
||||
gs_launch_detached "-Scanners $eng -Headless" "ve_$eng" || { echo "[ERROR] launch failed for $eng"; return 1; }
|
||||
gs_wait_detached "ve_$eng" "run-$eng" || true
|
||||
|
||||
# 3) check which seeded copies survived + read that run's result json
|
||||
cat > "$WORK_DIR/ve_check.ps1" <<'PS'
|
||||
|
||||
Reference in New Issue
Block a user