Bra*_*rad 9 error-handling powershell try-catch
我有一个相当大的PowerShell脚本,有许多(20+)个函数执行各种操作.
现在所有的代码都没有任何错误处理或重试功能.如果某个特定的任务/功能失败,它就会失败并继续.
我想改进错误处理并实现重试以使其更加健壮.
我在想类似的东西:
$tries = 0
while ($tries -lt 5) {
try{
# Do Something
# No retries necessary
$tries = 5;
} catch {
# Report the error
# Other error handling
}
}
Run Code Online (Sandbox Code Playgroud)
问题是我需要做很多步骤才能做到这一点.
我认为实施上述代码20次是没有意义的.这似乎真的是多余的.
我在考虑编写一个带有单个参数的"TryCatch"函数,该参数包含我想要调用的实际函数?
不过,我不确定这是正确的方法.我不会最终得到一个类似于以下内容的脚本:
TryCatch "Function1 Parameter1 Parameter2"
TryCatch "Function2 Parameter1 Parameter2"
TryCatch "Function3 Parameter1 Parameter2"
Run Code Online (Sandbox Code Playgroud)
有一个更好的方法吗?
Ans*_*ers 16
如果您经常需要多次重试动作的代码,您可以将循环包装try..catch在函数中并在scriptblock中传递命令:
function Retry-Command {
[CmdletBinding()]
Param(
[Parameter(Position=0, Mandatory=$true)]
[scriptblock]$ScriptBlock,
[Parameter(Position=1, Mandatory=$false)]
[int]$Maximum = 5,
[Parameter(Position=2, Mandatory=$false)]
[int]$Delay = 100
)
Begin {
$cnt = 0
}
Process {
do {
$cnt++
try {
$ScriptBlock.Invoke()
return
} catch {
Write-Error $_.Exception.InnerException.Message -ErrorAction Continue
Start-Sleep -Milliseconds $Delay
}
} while ($cnt -lt $Maximum)
# Throw an error after $Maximum unsuccessful invocations. Doesn't need
# a condition, since the function returns upon successful invocation.
throw 'Execution failed.'
}
}
Run Code Online (Sandbox Code Playgroud)
像这样调用函数(默认为5次重试):
Retry-Command -ScriptBlock {
# do something
}
Run Code Online (Sandbox Code Playgroud)
或者像这样(如果在某些情况下需要不同的重试次数):
Retry-Command -ScriptBlock {
# do something
} -Maximum 10
Run Code Online (Sandbox Code Playgroud)
该功能可以进一步改进,例如通过在$Maximum尝试失败后尝试使用另一个参数配置脚本终止,以便您可以拥有将导致脚本失败时停止的操作,以及可以忽略失败的操作.
我改编了@Victor 的回答并补充说:
sleep为Start-Sleep)# [Solution with passing a delegate into a function instead of script block](/sf/answers/3339896521/)
function Retry()
{
param(
[Parameter(Mandatory=$true)][Action]$action,
[Parameter(Mandatory=$false)][int]$maxAttempts = 3
)
$attempts=1
$ErrorActionPreferenceToRestore = $ErrorActionPreference
$ErrorActionPreference = "Stop"
do
{
try
{
$action.Invoke();
break;
}
catch [Exception]
{
Write-Host $_.Exception.Message
}
# exponential backoff delay
$attempts++
if ($attempts -le $maxAttempts) {
$retryDelaySeconds = [math]::Pow(2, $attempts)
$retryDelaySeconds = $retryDelaySeconds - 1 # Exponential Backoff Max == (2^n)-1
Write-Host("Action failed. Waiting " + $retryDelaySeconds + " seconds before attempt " + $attempts + " of " + $maxAttempts + ".")
Start-Sleep $retryDelaySeconds
}
else {
$ErrorActionPreference = $ErrorActionPreferenceToRestore
Write-Error $_.Exception.Message
}
} while ($attempts -le $maxAttempts)
$ErrorActionPreference = $ErrorActionPreferenceToRestore
}
# function MyFunction($inputArg)
# {
# Throw $inputArg
# }
# #Example of a call:
# Retry({MyFunction "Oh no! It happened again!"})
# Retry {MyFunction "Oh no! It happened again!"} -maxAttempts 10
Run Code Online (Sandbox Code Playgroud)
小智 7
将委托传递给函数而不是脚本块的解决方案:
function Retry([Action]$action)
{
$attempts=3
$sleepInSeconds=5
do
{
try
{
$action.Invoke();
break;
}
catch [Exception]
{
Write-Host $_.Exception.Message
}
$attempts--
if ($attempts -gt 0) { sleep $sleepInSeconds }
} while ($attempts -gt 0)
}
function MyFunction($inputArg)
{
Throw $inputArg
}
#Example of a call:
Retry({MyFunction "Oh no! It happend again!"})
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9536 次 |
| 最近记录: |