"""Kill farm loop processes on Windows: wrappers first (tree kill), verify to zero. Usage: python kill_farm_loops.py "regex_pattern" [max_rounds] Pattern uses bracket-trick against self-match, e.g. 'treg_farm_v[3]|v3_loo[p]'. Python subprocess instead of powershell one-liners: git-bash eats $_. """ import subprocess, sys, time, os PATTERN = sys.argv[1] if len(sys.argv) > 1 else r'treg_farm_v[34]|v[34]_loo[p]' MAX_ROUNDS = int(sys.argv[2]) if len(sys.argv) > 2 else 6 def ps(cmd): return subprocess.run(['powershell', '-NoProfile', '-Command', cmd], capture_output=True, text=True).stdout def find(pattern): out = ps(r'''Get-CimInstance Win32_Process | Where-Object {$_.CommandLine -match '%s'} | ForEach-Object {"$($_.ProcessId)|$($_.Name)|$($_.CommandLine)"}''' % pattern) rows = [] for l in out.splitlines(): parts = l.split('|', 2) if len(parts) >= 2 and parts[0].strip().isdigit(): rows.append((int(parts[0].strip()), parts[1].strip(), parts[2] if len(parts) > 2 else '')) me = os.getpid() return [r for r in rows if r[0] != me and 'kill_farm_loops' not in r[2] and 'Get-CimInstance' not in r[2]] for rnd in range(MAX_ROUNDS): rows = find(PATTERN) if not rows: print('ALL DEAD'); sys.exit(0) print(f'round {rnd}:', [(p, n) for p, n, _ in rows]) # wrappers (bash/sh running the loop script) FIRST — otherwise they respawn python children wrappers = [r for r in rows if '_loop' in r[2] or r[1].lower() in ('bash.exe', 'sh.exe')] others = [r for r in rows if r not in wrappers] for p, n, c in wrappers + others: subprocess.run(['taskkill', '/F', '/T', '/PID', str(p)], capture_output=True) time.sleep(3) print('STILL ALIVE after %d rounds — manual check' % MAX_ROUNDS) for p, n, c in find(PATTERN): print(p, n, c[:120]) sys.exit(1)