You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DomainPasswordSpray日志IO异常处理:寻求Try/Catch替代方案

解决DomainPasswordSpray日志写入冲突的三种实用方案

先明确:之前脚本耗时翻倍是无效用户名引发AD查询延迟,和Try/Catch、错误重定向无关,当前核心问题是高频日志写入导致的文件占用异常。以下是比Try/Catch更高效的解决办法:

1. 异步批量日志队列(最优解)

用线程安全队列暂存日志,后台线程定期批量写入,彻底避免前台写文件的冲突:

# 初始化线程安全日志队列
$logQueue = [System.Collections.Concurrent.ConcurrentQueue[string]]::new()

# 启动后台写入线程
$logThread = [System.Threading.Thread]::new({
    while ($true) {
        if ($logQueue.Count -gt 0) {
            $batchLogs = @()
            # 一次性取出队列中所有日志
            while ($logQueue.TryDequeue([ref]$entry)) {
                $batchLogs += $entry
            }
            # 批量追加到文件,减少IO次数
            Add-Content -Path "password_spray.log" -Value $batchLogs -ErrorAction SilentlyContinue
        }
        # 每500ms检查一次队列,可按需调整间隔
        Start-Sleep -Milliseconds 500
    }
})
$logThread.IsBackground = $true
$logThread.Start()

# 喷洒逻辑中只需把日志丢进队列,不用直接写文件
$logMsg = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - 尝试用户:$targetUser,密码:$testPass"
$logQueue.Enqueue($logMsg)

前台线程只做入队操作,几乎不占性能,后台批量写入彻底解决文件占用问题。

2. 带重试的独占文件锁

针对写入操作加独占锁,失败后短暂重试,比全局Try/Catch性能损耗小:

function Write-SafeLog {
    param(
        [string]$Message,
        [string]$LogPath
    )
    $maxRetries = 3
    $retryWait = 100 # 毫秒间隔
    $writeSuccess = $false

    for ($i=0; $i -lt $maxRetries; $i++) {
        try {
            # 申请文件独占访问权,无共享
            $fileStream = [System.IO.File]::Open($LogPath, [System.IO.FileMode]::Append, [System.IO.FileAccess]::Write, [System.IO.FileShare]::None)
            $streamWriter = [System.IO.StreamWriter]::new($fileStream)
            $streamWriter.WriteLine($Message)
            $streamWriter.Close()
            $fileStream.Close()
            $writeSuccess = $true
            break
        }
        catch [System.IO.IOException] {
            # 仅捕获文件占用异常,短暂重试
            Start-Sleep -Milliseconds $retryWait
        }
        catch {
            # 其他异常直接抛出,不吞错
            throw
        }
    }
    if (-not $writeSuccess) {
        Write-Warning "日志写入失败:$Message"
    }
}

# 调用示例
Write-SafeLog -Message "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - 尝试用户:$targetUser" -LogPath "password_spray.log"

只有写入失败时才重试,不会像全局Try/Catch那样拖慢整个脚本流程。

3. 线程独立日志文件(快速改造方案)

给每个并发线程分配单独的日志文件,脚本结束后合并:

# 每个线程用自身ID生成唯一日志文件名
$threadId = [System.Threading.Thread]::CurrentThread.ManagedThreadId
$threadLogPath = "spray_log_thread_$threadId.txt"

# 直接写入线程专属日志,无竞争
Add-Content -Path $threadLogPath -Value "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - 尝试用户:$targetUser"

# 脚本收尾阶段合并所有日志
Get-ChildItem "spray_log_thread_*.txt" | Sort-Object CreationTime | Get-Content | Add-Content "spray_log_merged.txt"
# 删除临时日志文件
Remove-Item "spray_log_thread_*.txt" -Force

这种方法无需复杂逻辑,快速解决冲突,合并日志的操作放在脚本最后,不影响喷洒流程性能。

内容的提问来源于stack exchange,提问作者Stumpy Jones

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 23:51:04