feature: NinjaRMM runaway script-log purge tool#102
Conversation
Reclaims disk from runaway custom-script output transcripts under the NinjaRMM agent scripting directory. Scans for *-output.txt over a configurable threshold (default 500MB), kills the writing process if still active, and hard-deletes the file. Dual-mode (interactive + RMM), runs silently with no required input. Self-protecting: excludes its own PID from process kills and treats a locked file as a counted failure rather than silent success. 64-bit relaunch guard for NinjaRMM's 32-bit default host. Tested both modes on a workstation: EXIT 0 nothing-to-clean.
There was a problem hiding this comment.
Code review is billed via overage credits. To resume reviews, an organization admin can raise the monthly limit at claude.ai/admin-settings/claude-code.
Once credits are available, push a new commit or reopen this pull request to trigger a review.
The initial command-line substring match failed to identify the writer on a live runaway (multi-process cmd/powershell tree, GUID-style customscript_src_<guid> filename). Replaced with Windows Restart Manager (rstrtmgr.dll) interop to query the exact PIDs holding each oversized output file, with a hard guard that never terminates the NinjaRMM agent or this script's own process. Added 3x delete retry for non-instant handle release. Fixes $hpid parse error in kill-failure path. Validated destructive path on a live 9.3GB runaway: holders identified, terminated, file deleted, EXIT 0.
The threshold-only scan missed freshly-respawned runaways still small at scan time (confirmed: tool reported nothing over 500MB while a NinjaRMM customscript spun a Read-Host NonInteractive loop into its output). Added a 3s growth-sampling pass: a file is a runaway if over ThresholdMB, OR growing while held by a NinjaRMM customscript process, OR its holder has run past RuntimeCeilingMin (default 30, backstop). Holder lookup factored into Get-ScriptHolder with proper error handling. Restart Manager kill, agent self-protection, and 3x delete retry unchanged.
|
Added growth-based detection. Threshold-only scan missed runaways still small at scan time. Tool now flags a file as runaway on any of: over ThresholdMB, actively growing while held by a NinjaRMM customscript process (3s sample), or holder past RuntimeCeilingMin (default 30, backstop). New optional RMM var: RuntimeCeilingMin. |
… output Threshold-only scan missed freshly-respawned runaways still small at scan time, and the tool false-failed trying to delete its own live output file when run via NinjaRMM. Now: snapshots sizes, samples 3s growth, flags a file as runaway if over ThresholdMB OR growing while held by a NinjaRMM customscript process OR holder past RuntimeCeilingMin (default 30). Captures own PID+parent up front and excludes files they hold open, so the tool never targets its own transcript. Restart Manager kill, agent self-protection, 3x delete retry unchanged. Validated via NinjaRMM against a live 11.48GB runaway: real file cleaned; prior false-positive on own output eliminated.
|
Added growth detection + self-output exclusion. Tool now flags a file as runaway on any of: over ThresholdMB, growing while held by a NinjaRMM customscript process (3s sample), or holder past RuntimeCeilingMin (default 30, backstop). Also captures its own PID+parent and excludes files they hold open, fixing a false-positive FAILURE where the tool tried to delete its own live output transcript when run via NinjaRMM. New optional RMM var: RuntimeCeilingMin. Validated via NinjaRMM against a live 11.48GB runaway. |
## What this does
Adds a NinjaRMM remediation script that reclaims disk consumed by runaway custom-script output transcripts under
C:\\ProgramData\\NinjaRMMAgent\\scripting. Scans for\*-output.txtfiles over a configurable size threshold (default 500MB), kills the writing process if one is still active, and hard-deletes the file.## Why
Custom scripts that hit an interactive branch in a console-less context (e.g.
Read-Hostunder NonInteractive) can spin a loop that writes into the script's output transcript until the disk fills — observed at 20GB+ on a single file. This tool is the cleanup/remediation capability; the underlying interactive-branch bug in the offending script(s) is tracked separately.## Design notes
- **Dual-mode**: runs identically interactive or via RMM (
$env:RMM -eq "1"). No required user input — Description defaults silently, ThresholdMB is optional. No interactive prompt by design (an interactive prompt is the exact failure mode this tool cleans up after).- **Self-protecting**: excludes its own PID from process kills (
$\_.ProcessId -ne $myPid) and anchors the writer match on both the scripting path and the gen-id, so it cannot kill its own run. A locked file is treated as a counted failure (EXIT 1), not a silent success.- **64-bit relaunch guard**: NinjaRMM launches 32-bit PowerShell by default; the script relaunches under the native host so behavior is identical across invocation paths.
- **Exit codes**: 0 = completed (no failures), 1 = one or more deletion failures, 2 = scripting dir not found.
## Testing performed
Smoke-tested both modes on a workstation (LT-5226):
- Interactive: scanned, no files over threshold, EXIT 0.
- RMM simulation (
$env:RMM="1",ThresholdMB=500): same path, EXIT 0.PSScriptAnalyzer: clean except
PSAvoidUsingWriteHost(known repo convention — output goes toStart-Transcript/RMM console capture).## RMM compatibility
Reads
$env:RMM,$env:Description,$env:ThresholdMBper repo input-handling convention. Logs viaStart-Transcriptto$env:RMMScriptPath\\logs\\(RMM) or$env:WINDIR\\logs\\(interactive/fallback).