PowerShell变量赋值随机失败

时间:2013-04-30 12:46:39

标签: sql powershell

我有一个奇怪的问题,大概只发生在100次中的1次。我有一个PowerShell脚本使用SQL的SMO库来进行数据库备份。以下是我用于解决问题的相关代码的片段:

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | out-null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended") | out-null
$now = get-date
########################################
$server = new-object Microsoft.SqlServer.Management.Smo.Server
$server.ConnectionContext.StatementTimeout = 86400 # Allow backups to take up to 24 hours per database
$databases = $server.Databases
$script:totalsteps = $databases.count
########################################
if($script:totalsteps -eq $null -or $script:totalsteps -eq 0) {
    $body = "Backup start:" +  $now.tostring("yyyy-MM-dd hh:mm:ss tt") + "`r`n" + 
        "Error: " + (get-date).tostring("yyyy-MM-dd hh:mm:ss tt") + "`r`n" + 
        "`$script:totalsteps: " + $script:totalsteps + "`r`n" + 
        "`$databases.count: " + $databases.count + "`r`n" + 
        "`$databases: " + $databases + "`r`n" + 
        "`$server: " + $server
    send-mailmessage -from "me@example.com" -to "me@example.com" -subject "Server Null: $server" -smtpserver "mail.example.com" -body $body
}

问题是,偶尔会将if语句评估为true,并且会收到一封类似以下内容的电子邮件:

Backup start: 2013-04-30 07:50:58 AM
Error: 2013-04-30 08:02:19 AM
$script:totalsteps: 
$databases.count: 4
$databases: [master] [model] [msdb] [tempdb]
$server: [serverA]

值得注意的是,脚本开始时间与错误时间大致相差11分钟,这有点奇怪。我现在唯一的猜测是服务器承受了很大的压力,因此PowerShell默默地对变量赋值失败并继续运行。

if语句的100次中有99次是假的,我没有收到电子邮件。我无法理解为什么$script:totalsteps分配在100%的时间内不起作用。有任何想法吗?我可以做些什么来试图解决这个问题?

更新

为了测试惰性评估理论,我将代码更改为:

System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | out-null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended") | out-null
$now = get-date
########################################
$server = new-object Microsoft.SqlServer.Management.Smo.Server
$server.ConnectionContext.StatementTimeout = 86400 # Allow backups to take up to 24 hours per database
$databases = $server.Databases
$script:totalsteps = $databases.count
############ NEW NEW NEW NEW ###########
if($script:totalsteps -eq $null -or $script:totalsteps -eq 0)
{
    $script:totalsteps = $databases.count * 4
    send-mailmessage -from "me@example.com" -to "me@example.com" -subject "Server Null: $server" -smtpserver "mail.example.com" -body "FIRST ATTEMPT"
}
########################################
if($script:totalsteps -eq $null -or $script:totalsteps -eq 0)
{
    $body = "Backup start:" +  $now.tostring("yyyy-MM-dd hh:mm:ss tt") + "`r`n" + 
        "Error: " + (get-date).tostring("yyyy-MM-dd hh:mm:ss tt") + "`r`n" + 
        "`$script:totalsteps: " + $script:totalsteps + "`r`n" + 
        "`$databases.count: " + $databases.count + "`r`n" + 
        "`$databases: " + $databases + "`r`n" + 
        "`$server: " + $server
    send-mailmessage -from "me@example.com" -to "me@example.com" -subject "Server Null: $server" -smtpserver "mail.example.com" -body $body
}

1 个答案:

答案 0 :(得分:2)

这里只是猜测,但由于赋值是对$databases变量的第一次访问:我认为对它们的评估是懒惰的,所以当它尝试枚举数据库时你可能会因为它首先需要而超时打开连接。之后,您已经获取了数据,因此第二次使用时可以使用它。但是,有点难以验证。

我建议您使用您的电子邮件发送$Error变量,它实际上可能包含原因