Powershell - 在输出特定字符串时终止命令

Powershell - terminate command when it outputs a certain string

我在 PowerShell 中有一个命令 运行ning,它会莫名其妙地出错(每当网络连接饱和时,它就会出错)

出错后,它将不再按预期运行,而是继续运行。错误也不会打印为错误,就像标准文本一样。

我想让命令 运行ning 在一个循环中检测它何时出错,然后终止它,然后重新启动它,但是我一直找不到任何关于解析命令输出的信息实时。

例如:foo.ps1每秒输出一个数字,但会随机开始每秒输出一次"ERROR: CONNECTION SATURATED"。我如何创建一个循环来检测、终止进程并重新启动它?

编辑: command erroring 这就是命令错误的样子。如您所见,错误 (Warning: ring buffer overflow!!!) 打印为标准输出,而不是错误。

您可以使用trap关键字来检测错误并进行处理,即

function Test {
    Write-Host "Doing something..."
    trap {
        Write-Host "Error found:"
        break
    }

    Write-Host "Code should not reach here"
}

要捕获特定的异常,您可以指定要捕获的内容

...
trap [TheExceptionYouWantToCatch]{
...
}
...

这很奇怪,但是 "select -first 1" 在找到答案时会终止管道。这样只会运行只持续5秒

& { foreach ($i in 1..10) { $i; sleep 1 } } | where { $_ -eq 5 } | 
  select -first 1  

不言而喻,您不能使用标准的 PowerShell 错误处理机制,因为您的命令既不会引发异常也不会写入错误流。因此,您必须在生成时解析命令的输出(即异步)。

运行 命令并异步访问其输出的最简单方法是使用作业。因此,以下脚本应该可以完成您的要求:

param(
    # Specifies the commands to run in the job.
    [ScriptBlock] $ScriptBlock,

    # Specifies the text for which to search in each line of the output.
    [string] $Pattern = '^\s*(Warning|Error)',

    # Specifies how long to sleep in seconds between output searches.   
    [int] $Seconds = 1
)

while ($true) {
    $job = Start-Job $ScriptBlock
    while ($job.State -eq 'Running') {
        $output = Receive-Job $job
        if ($output -match $Pattern) {
            break
        }
        Start-Sleep $Seconds
    }
    Stop-Job $job
}

根据您的要求,您可能还想:

  • 扩大可接受的集合job states
  • 如果遇到某些特定的作业状态或其他输出模式,则完全终止脚本(即而不重新启动作业)。