Powershell 从 rabbitmqctl 获取输出并解析异常
Powershell get output from rabbitmqctl and parse exception
我正在从 Powrshell 调用 rabbitmqctl:
$out = (& $path ($arguments -split " ") )
Write-Host $out
路径正确,输出成功信息:
Clearing policy "<policyname>" on vhost "<vhost>" ...
路径不正确,出现异常:
....
+ CategoryInfo : NotSpecified: (Error::String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
Parameter does not exist
消息 Clearing policy
丢失。停止执行时,$_.Exception.Message为空。
try {
$ErrorActionPreference = 'Stop'
...
}
catch {
Write-Warning $_.Exception.Message
}
有没有办法同时获取 Clearing policy
消息和最后一行 Parameter does not exist
?
tl;dr:将错误流重定向到stdout
并将每个元素转换为字符串:
$out = (& $path ($arguments -split " ") 2>&1) | % ToString
执行外部程序时(如rabbitmqctl
),您不会收到任何异常。您可能会在不同的流中获得输出(主要是 stdout
和 stderr
),并且您的外部程序将 return 一个错误代码,但肯定不是异常,PowerShell 可以处理。
我猜你正在使用 PowerShell ISE。为什么?因为与 PowerShell 相比,PowerShell ISE 具有奇怪的行为,如果它被强制打印从外部程序的错误流中接收到的文本,则会抛出异常。
您可以使用以下命令重现它:
where.exe nonExistentExecutable.bla
在 PowerShell 中,它会输出一些文本,说明找不到具有该模式的文件。在 PowerShell ISE 中,您将得到一个 NativeCommandError
异常,其中包含来自错误流的文本。
这里的关键点是,如果必须报告错误,大多数可执行文件都会写入错误流。 where.exe
也是如此,在您的情况下 rabbitmqctl
也是如此。您不能像那样捕获错误流:
$out = (& $path ($arguments -split " ") )
这只会捕获成功流(又名 stdout
)。错误流将转发到控制台,ISE 将抛出异常。这就是你的情况。要同时捕获错误流,请将其重定向到 stdout
:
$out = (& $path ($arguments -split " ") 2>&1)
现在,$out
肯定会捕获结果,要么是成功消息,要么是错误消息。在错误流的情况下,每一行都将由 [System.Management.Automation.ErrorRecord]
包裹,甚至 PowerShell(如 ISE)也会以异常的形式输出。为防止这种情况,将每个元素转换为字符串:
$out = (& $path ($arguments -split " ") 2>&1) | % ToString
这不会对成功消息产生负面影响,因此可以在任何情况下使用。
我正在从 Powrshell 调用 rabbitmqctl:
$out = (& $path ($arguments -split " ") )
Write-Host $out
路径正确,输出成功信息:
Clearing policy "<policyname>" on vhost "<vhost>" ...
路径不正确,出现异常:
....
+ CategoryInfo : NotSpecified: (Error::String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
Parameter does not exist
消息 Clearing policy
丢失。停止执行时,$_.Exception.Message为空。
try {
$ErrorActionPreference = 'Stop'
...
}
catch {
Write-Warning $_.Exception.Message
}
有没有办法同时获取 Clearing policy
消息和最后一行 Parameter does not exist
?
tl;dr:将错误流重定向到stdout
并将每个元素转换为字符串:
$out = (& $path ($arguments -split " ") 2>&1) | % ToString
执行外部程序时(如rabbitmqctl
),您不会收到任何异常。您可能会在不同的流中获得输出(主要是 stdout
和 stderr
),并且您的外部程序将 return 一个错误代码,但肯定不是异常,PowerShell 可以处理。
我猜你正在使用 PowerShell ISE。为什么?因为与 PowerShell 相比,PowerShell ISE 具有奇怪的行为,如果它被强制打印从外部程序的错误流中接收到的文本,则会抛出异常。
您可以使用以下命令重现它:
where.exe nonExistentExecutable.bla
在 PowerShell 中,它会输出一些文本,说明找不到具有该模式的文件。在 PowerShell ISE 中,您将得到一个 NativeCommandError
异常,其中包含来自错误流的文本。
这里的关键点是,如果必须报告错误,大多数可执行文件都会写入错误流。 where.exe
也是如此,在您的情况下 rabbitmqctl
也是如此。您不能像那样捕获错误流:
$out = (& $path ($arguments -split " ") )
这只会捕获成功流(又名 stdout
)。错误流将转发到控制台,ISE 将抛出异常。这就是你的情况。要同时捕获错误流,请将其重定向到 stdout
:
$out = (& $path ($arguments -split " ") 2>&1)
现在,$out
肯定会捕获结果,要么是成功消息,要么是错误消息。在错误流的情况下,每一行都将由 [System.Management.Automation.ErrorRecord]
包裹,甚至 PowerShell(如 ISE)也会以异常的形式输出。为防止这种情况,将每个元素转换为字符串:
$out = (& $path ($arguments -split " ") 2>&1) | % ToString
这不会对成功消息产生负面影响,因此可以在任何情况下使用。