2013-04-30 72 views
2

我有一个奇怪的问题,大概只有100次出现。我有一个使用SQL的SMO库进行数据库备份的PowerShell脚本。下面是我用来解决该问题的相关代码剪断:PowerShell变量赋值随机失败

[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 "[email protected]" -to "[email protected]" -subject "Server Null: $server" -smtpserver "mail.example.com" -body $body 
} 

的问题是,曾经在一段时间的if语句评价真实,我得到的是看起来的电子邮件,如:

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默默地失败了变量赋值,并且继续前进。

99的100次if语句是错误的,我没有收到电子邮件。我不明白为什么$script:totalsteps作业没有100%的时间工作。有任何想法吗?还有什么可以尝试解决此问题?

UPDATE

为了测试懒惰评价理论,我已经改变了代码为:

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 "[email protected]" -to "[email protected]" -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 "[email protected]" -to "[email protected]" -subject "Server Null: $server" -smtpserver "mail.example.com" -body $body 
} 
+0

只是猜测这里,但因为任务是在'$ databases'变量的第一次访问。我相信这些评估是懒惰的,所以当它试图枚举数据库时可能会超时,因为它首先需要打开一个连接。之后,您已经提取了数据,因此当您第二次使用该数据时可用。虽然有点难以验证。 – carlpett 2013-04-30 13:45:46

+2

我会建议沿着'$ Error'变量发送邮件,它可能实际上包含原因 – carlpett 2013-04-30 13:46:28

+0

好的想法。一位同事建议在分配和if语句之间增加一个睡眠,所以我已经做到了。我还在电子邮件中添加了$ error变量。我敢打赌你第一次懒惰的评估是正确的。我可能会尝试在if语句中重新分配变量以查看是否修复了它。但是,在我看到我刚刚做出的改变证明是否有用之后,我会尝试一下。我将在第二天或第二天更新。 – 2013-04-30 14:51:58

回答

2

只是猜测这里,但由于分配是在第一次访问$databases变量:我相信对它们的评估是懒惰的,所以当它试图枚举数据库时可能会超时,因为它首先需要打开一个连接。之后,您已经提取了数据,因此当您第二次使用该数据时可用。虽然有点难以验证。

我建议连同您的电子邮件$Error变量中发送为好,它实际上可能包含的原因