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

PowerShell如何实现日志超5分钟无活动的检测触发功能

PowerShell 日志5分钟无活动检测实现方案

核心逻辑是放弃原代码中Get-Content -Wait的阻塞式监听,改用非阻塞的轮询机制,独立维护最后活动时间戳,在不影响原有日志匹配处理逻辑的前提下实现超时检测。

实现要点

  • 初始化时记录最后一次日志活动时间,设置5分钟超时阈值,新增防重复通知标记避免同一段无活动周期内重复触发通知
  • 用文件流指针记录读取位置,每次轮询只读取上次读取后新增的日志内容,和原代码-Tail 1 -Wait的行为保持一致,不会重复处理历史日志
  • 每次读取到匹配myapp规则的新日志行时,立刻重置最后活动时间、清除通知触发标记,同时执行原有的行处理逻辑
  • 每轮轮询计算当前时间和最后活动时间的差值,达到5分钟阈值且未发过通知时,直接调用你已编写完成的通知函数
  • 兼容WebSphere日志滚动切割场景,日志被切走生成新文件时会自动定位到新的日志文件继续监听

可直接运行的完整代码

$File = "server.log"
$Path = "D:\IBM\WebSphere\AppServer\profiles\AppSrv01\logs"
$timeoutThreshold = New-TimeSpan -Minutes 5
$pollInterval = 10 # 轮询间隔,单位秒,可根据精度需求调整

# 定位目标日志文件
$result = Get-ChildItem $Path -Recurse | Where-Object { $_.Name -match $File } | Sort-Object LastWriteTime -Descending | Select-Object -First 1
if (-not $result) {
    throw "目标路径下未找到匹配的日志文件"
}
$currentLogPath = $result.FullName

# 初始化状态变量
$lastActivityAt = Get-Date
$hasSentTimeoutNotice = $false
$lastReadPosition = 0

# 初始定位到文件末尾,和原代码-Tail行为对齐,不处理历史日志
$initStream = [System.IO.FileStream]::new($currentLogPath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite)
$initStream.Seek(0, [System.IO.SeekOrigin]::End) | Out-Null
$lastReadPosition = $initStream.Position
$initStream.Close()

while ($true) {
    Start-Sleep -Seconds $pollInterval

    # 日志滚动/删除检测,自动重连新日志文件
    if (-not (Test-Path $currentLogPath)) {
        $newLog = Get-ChildItem $Path -Recurse | Where-Object { $_.Name -match $File } | Sort-Object LastWriteTime -Descending | Select-Object -First 1
        if ($newLog) {
            $currentLogPath = $newLog.FullName
            $lastReadPosition = 0
            $lastActivityAt = Get-Date
            $hasSentTimeoutNotice = $false
        }
        continue
    }

    # 读取新增日志内容
    $readStream = [System.IO.FileStream]::new($currentLogPath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite)
    $reader = [System.IO.StreamReader]::new($readStream)
    $readStream.Seek($lastReadPosition, [System.IO.SeekOrigin]::Begin) | Out-Null
    $newContent = $reader.ReadToEnd()
    $lastReadPosition = $readStream.Position
    $reader.Close()
    $readStream.Close()

    # 处理匹配规则的新日志行
    if (-not [string]::IsNullOrWhiteSpace($newContent)) {
        $matchedLines = $newContent -split "`r?`n" | Where-Object { $_ -match "myapp" }
        if ($matchedLines.Count -gt 0) {
            # 重置活动状态
            $lastActivityAt = Get-Date
            $hasSentTimeoutNotice = $false
            # 原有日志处理逻辑
            foreach ($line in $matchedLines) {
                "Another line was added: " + $line
            }
        }
    }

    # 超时判断
    $idleDuration = (Get-Date) - $lastActivityAt
    if ($idleDuration -ge $timeoutThreshold -and -not $hasSentTimeoutNotice) {
        # ==== 此处替换为你自己编写的通知函数调用即可 ====
        # 示例:Invoke-YourNotificationFunction
        Write-Host "检测到日志已超过5分钟无匹配活动,触发通知"
        # ==============================================
        $hasSentTimeoutNotice = $true
    }
}

补充说明

  • 超时检测的误差最大不超过你设置的轮询间隔时长,默认10秒间隔对服务器性能几乎无影响
  • 通知只会在首次达到5分钟无活动阈值时触发一次,不会重复发送,直到下一次匹配的新日志写入后才会重置状态
  • 代码保留了原脚本所有原有行为,不会影响你之前的日志匹配处理逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 20:12:26