作为脚本语言,当我们往往关心的是如何实现功能,更好更快更简短的实现越来越灵活的需求,这些功能大多可能是一次性的,所以不怎么重视其错误处理。。作为脚本语言,powershell 既灵活,功能又强大,语法精炼,容错性高。对于功能复杂的业务场景,这种思维往往使人深受其害,笔者也是后知后觉,如何灵活且正确的捕获处理和异常,在shell编程中也很重要。
全局错误处理偏好
$ErrorActionPreference
可以看到,Powershell 全局错误处理偏好为 continue.
Continue : 当命令执行出错,抛出异常并继续执行下一条命令
Stop : 当命令执行出错,抛出异常并停止执行。
SilentlyContinue :当shell执行抛出异常,
Inquire : 当命令执行出错,powershell 会询问用户是否继续执行或者放弃
错误处理偏好可分为两种,终止偏好或者非终止偏好,
当为终止偏好时(Stop, Inquire:Stop , ), 抛出的错误会被记录在command指定的错误变量中(ErrorVariable),如果没有指定变量,错误将会被追加在 全局运行时错误集合 $Error 中。 在终止偏好的作用域中可以使用try,catch异常捕获。
当为非终止偏好 (Continue, Inquire:Continue,SilentlyContinue), 抛出的错误不会被记录在指定的错误变量中(使用 ErrorVariable 无效), 但会被记录在全局运行时错误集合($Error)中, 在非终止偏好的作用域中错误无法被Try Catch 捕获
Command 中的 ErrorAction 参数
从powershell 2.0 开始引入了高级方法,当一个方法被标记为cmdletbinding()时,该方法在被编译时会添加powershell 的通用cmdlet 参数。 其中就有ErrorAction. 除此之外还有,Verbose,Debug,ErrorVariable,OutVariable等等
ErrorAction同全局的错误处理偏好$ErrorActionPreference 一样,并且从PS3.0开始加入了Ignore选项,该选项既不会抛错也不会将错误写入全局错误集合, 该选项不能与 ErrorVariable 参数配合使用, 也不能被Try Catch所捕获
ErrorVariable & Try Catch 流程控制
可以看出在终止偏好代码中 ErrorVariable, Try Catch 可以作为的异常捕获方式,前者负责异常捕获,后者负责流程控制,
而在非终止偏好的代码块,使用全局异常集合$Error获取异常,使用$?判断上一条命令是否成功,从而实现异常捕获与流程控制。
这两种方式极大的扩展了异常捕获和流程控制灵活性。
注意: 对于Invoke-Expression 和 Invoke-Command 当传入的命令(块)执行出错时,异常无法被外层的ErrorVariable 所捕获,而仅仅被被全局的$Error所捕获, 并且powershell认为该条命令已经执行成功。