执行命令不会导致脚本异常
Executing command doesn't result in script exception
我们有一个部署数据库脚本的 powershell 脚本。但是,如果数据库脚本失败,输出不会向 powershell 脚本抛出异常。
下面是 .ps1 文件的示例:
function Publish-DatabaseProject
{
sqlcmd -S . -b -v DatabaseName=Integration -q "alter table xx add test Varchar(10)"
}
function Add-Timestamp {
process {
if ($_.GetType() -eq [string]) {
"[$(Get-Date -Format o)] $_"
} else {
$_
}
}
}
function Write-LogFile {
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)] [string] $Path,
[Parameter(Mandatory=$true, ValueFromPipeline=$true)] [object[]] $InputObject
)
begin {
$root = Split-Path -Path $Path -Parent
if ($root -and !(Test-Path -Path $root)) { New-Item -Path $root -Type Directory
| Out-Null }
}
process {
$InputObject |
Add-Timestamp |
Tee-Object -File $Path -Append
}
}
Publish-DatabaseProject -ErrorVariable DeployError 2>&1 |
Write-LogFile -Path "C:\output.log"
if ($DeployError -and $DeployError.Count -ne 0)
{
Write-Output "Failed"
} else
{
Write-Output "Succeeded"
}
有问题的查询正在针对不存在的 table 执行。文本输出显示:
[2015-12-11T14:42:45.1973944+00:00] Msg 4902, Level 16, State 1, Server ABDN-DEV-PC1, Line 1
[2015-12-11T14:42:45.2053944+00:00] Cannot find the object "xx" because it does not exist or you do not have permission
s.
Succeeded
我希望最后一行显示为:失败。
如果您单独 运行 sqlcmd 行,然后使用 $LastExitCode
跟进它,它会吐出一个非零退出代码。
> sqlcmd -S . -b -v DatabaseName=Integration -q "alter table xx add test Varchar(10)"
Msg 4902, Level 16, State 1, Server ABDN-DEV-PC1, Line 1
Cannot find the object "xx" because it does not exist or you do not have permissions.
> $LastExitCode
1
由于种种原因,我们无法使用Invoke-SqlCmd
,需要坚持使用SQLCMD.exe。
我们如何才能使 SQLCMD 中的异常正确地冒出到调用脚本?
您的 -ErrorVariable DeployError
语句只有在 Publish-DatabaseProject
cmdlet 本身无法执行时才会被触发。由于该函数主要是 sqlcmd.exe 的包装器,因此没有任何智能可以引发此错误。我们可以使用 $LastExitCode
自动变量包装它。
function Publish-DatabaseProject
{
sqlcmd -S . -b -v DatabaseName=Integration -q "alter table xx add test Varchar(10)"
if ($LastExitCode -ne 0)
{
Write-error $LastExitCode
throw $LastExitCode
}
}
现在,PowerShell 将从 .exe 中捕获此错误,您可以使用 -ErrorVariable
.
更新
所以,既然你想保留 运行 而不是在遇到错误时弃船,我们需要用 try{}catch{}
块包装你的 Publish-DataBaseProject
函数,以捕获错误我们正在生成,不会停止执行。
try {Publish-DatabaseProject -ErrorAction STOP -ErrorVariable DeployError 2>&1 |
Write-LogFile -Path "C:\output.log" }
catch{
Write-Output "Current job $($_), failed"
Write-Output "Exception $($Error.ExceptionID)"
}
现在我们正确地从 CMD 生成异常,通过我们的函数将其冒泡,并像处理普通函数一样处理它,所有这些都使用 Native PowerShell。我相信这就是您想要做的。如果没有,post 整个脚本的要点,我会以更有针对性的方式帮助您。
我们有一个部署数据库脚本的 powershell 脚本。但是,如果数据库脚本失败,输出不会向 powershell 脚本抛出异常。
下面是 .ps1 文件的示例:
function Publish-DatabaseProject
{
sqlcmd -S . -b -v DatabaseName=Integration -q "alter table xx add test Varchar(10)"
}
function Add-Timestamp {
process {
if ($_.GetType() -eq [string]) {
"[$(Get-Date -Format o)] $_"
} else {
$_
}
}
}
function Write-LogFile {
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)] [string] $Path,
[Parameter(Mandatory=$true, ValueFromPipeline=$true)] [object[]] $InputObject
)
begin {
$root = Split-Path -Path $Path -Parent
if ($root -and !(Test-Path -Path $root)) { New-Item -Path $root -Type Directory
| Out-Null }
}
process {
$InputObject |
Add-Timestamp |
Tee-Object -File $Path -Append
}
}
Publish-DatabaseProject -ErrorVariable DeployError 2>&1 |
Write-LogFile -Path "C:\output.log"
if ($DeployError -and $DeployError.Count -ne 0)
{
Write-Output "Failed"
} else
{
Write-Output "Succeeded"
}
有问题的查询正在针对不存在的 table 执行。文本输出显示:
[2015-12-11T14:42:45.1973944+00:00] Msg 4902, Level 16, State 1, Server ABDN-DEV-PC1, Line 1
[2015-12-11T14:42:45.2053944+00:00] Cannot find the object "xx" because it does not exist or you do not have permission s.
Succeeded
我希望最后一行显示为:失败。
如果您单独 运行 sqlcmd 行,然后使用 $LastExitCode
跟进它,它会吐出一个非零退出代码。
> sqlcmd -S . -b -v DatabaseName=Integration -q "alter table xx add test Varchar(10)"
Msg 4902, Level 16, State 1, Server ABDN-DEV-PC1, Line 1
Cannot find the object "xx" because it does not exist or you do not have permissions.
> $LastExitCode
1
由于种种原因,我们无法使用Invoke-SqlCmd
,需要坚持使用SQLCMD.exe。
我们如何才能使 SQLCMD 中的异常正确地冒出到调用脚本?
您的 -ErrorVariable DeployError
语句只有在 Publish-DatabaseProject
cmdlet 本身无法执行时才会被触发。由于该函数主要是 sqlcmd.exe 的包装器,因此没有任何智能可以引发此错误。我们可以使用 $LastExitCode
自动变量包装它。
function Publish-DatabaseProject
{
sqlcmd -S . -b -v DatabaseName=Integration -q "alter table xx add test Varchar(10)"
if ($LastExitCode -ne 0)
{
Write-error $LastExitCode
throw $LastExitCode
}
}
现在,PowerShell 将从 .exe 中捕获此错误,您可以使用 -ErrorVariable
.
更新
所以,既然你想保留 运行 而不是在遇到错误时弃船,我们需要用 try{}catch{}
块包装你的 Publish-DataBaseProject
函数,以捕获错误我们正在生成,不会停止执行。
try {Publish-DatabaseProject -ErrorAction STOP -ErrorVariable DeployError 2>&1 |
Write-LogFile -Path "C:\output.log" }
catch{
Write-Output "Current job $($_), failed"
Write-Output "Exception $($Error.ExceptionID)"
}
现在我们正确地从 CMD 生成异常,通过我们的函数将其冒泡,并像处理普通函数一样处理它,所有这些都使用 Native PowerShell。我相信这就是您想要做的。如果没有,post 整个脚本的要点,我会以更有针对性的方式帮助您。