使用PowerShell进行随机WebRequest的结果

3
我有以下代码片段,脚本使用 WebRequest 对一组网站/应用服务器进行 ping 测试,但依赖于服务器列表中的好坏服务器的顺序,结果会出现随机性。
例如,如果先列出404或503的不良服务器,则脚本的报告似乎是准确的。然而,如果首先列出状态为“OK”的好服务器,则结果不准确。
以下是我的代码片段:
$ServerList = gc "$pwd\servers\test_servers.lst"
ForEach ($_ in $ServerList)
{   
# Ping web server test
$url = "http://$_.domain.net/logon"
Write-Host "Pinging web address for server: $url ..."
$request = [System.Net.WebRequest]::Create($url)
$response = $request.GetResponse()
If ($response.StatusCode -eq "OK") 
{
    #$True
    Write-Host "Web Ping on $_ Succeeded."
} 
Else 
{
    #$False
    Write-Host "Web Ping on $_ FAILED!!!"
}       
}

这是一个服务器列表示例:
server1 (reports back a 404)
server2 (reports back a 503)
server3 (gets a status = "OK")

当我运行脚本时,以下是“准确”的命令行输出:

C:\TFS\Sandbox>powershell ./temp.ps1

Pinging web address for server: http://server1.domain.net/wfc/logon ...
Exception calling "GetResponse" with "0" argument(s): "The remote server return
ed an error: (404) Not Found."
At C:\TFS\Sandbox\temp.ps1:8 char:34
+     $response = $request.GetResponse <<<< ()
+ CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Web Ping on server1 FAILED!!!

Pinging web address for server: http://server2.domain.net/wfc/logon ...
Exception calling "GetResponse" with "0" argument(s): "The remote server return
ed an error: (503) Server Unavailable."
At C:\TFS\Sandbox\temp.ps1:8 char:34
+     $response = $request.GetResponse <<<< ()
+ CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Web Ping on server2 FAILED!!!

Pinging web address for server: http://server3.domain.net/wfc/logon ...
Web Ping on server3 Succeeded.

现在如果我重新排列服务器列表,将好的服务器放在第一位,像这样:
server3 (gets a status = "OK")    
server1 (reports back a 404)
server2 (reports back a 503)

我得到了不准确的结果,其中服务器1和服务器2被报告为正常:

Pinging web address for server: http://server3.domain.net/wfc/logon ...
Web Ping on server3 Succeeded.

Pinging web address for server: http://server1.domain.net/wfc/logon ...
Exception calling "GetResponse" with "0" argument(s): "The remote server return
ed an error: (404) Not Found."
At C:\TFS\Sandbox\temp.ps1:8 char:34
+     $response = $request.GetResponse <<<< ()
+ CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Web Ping on server1 Succeeded.

Pinging web address for server: http://server2.domain.net/wfc/logon ...
Exception calling "GetResponse" with "0" argument(s): "The remote server return
ed an error: (503) Server Unavailable."
At C:\TFS\Sandbox\temp.ps1:8 char:34
+     $response = $request.GetResponse <<<< ()
+ CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Web Ping on server2 Succeeded.

为什么服务器列表不同会导致结果不一致?
谢谢!
2个回答

11

你可能需要关闭你的连接:

$response.Close()

http://msdn.microsoft.com/en-us/library/system.net.webresponse.close(v=vs.90).aspx

foreach ($server in $ServerList) {
    try {
        $url = "http://${server}.domain.net/logon"
        Write-Host "Pinging web address for server: $url ..."
        $request = [System.Net.WebRequest]::Create($url)
        $response = $request.GetResponse()
        Write-Host "Web Ping on $server Succeeded."   
    } catch {
        Write-Host ("Web Ping on $server FAILED!!! The error was '{0}'." -f $_)
    } finally {
        if ($response) {
            $response.Close()
            Remove-Variable response
        }
    }
}

虽然关闭响应是好的,但它并没有解决 OP 的问题,即对失败的任务返回成功。 - manojlds
@manojlds 我添加了一个 Remove-Variable,以防它在赋值时没有被清空。 - Andy Arismendi
@AndyArismendi -- 谢谢您的反馈。我也尝试了您的解决方案,它很有效! - Keith
@Keith 没问题,我稍微更新了一下,按照我完整的方式来做。 - Andy Arismendi
这对我解决了另一个问题。非常感谢!+1 - Vasili Syrakis

4
由于 WebRequest 在不成功的尝试时会引发异常,所以在出现 503404 等情况下,$response 并没有真正被设置。当您获得成功时,响应被设置为成功状态(状态码为 OK)。但是如果下一个服务器返回了 404,那么响应仍将保持在 OK 状态,因为 WebRequest 只会引发异常而不会给 $response 赋值。您可能希望在这里捕捉异常并处理成功或失败,或者在每次循环迭代中将 $response 设置为 null。
foreach($server in $serverlist){
$response=$null

...

另外,不要用$_作为迭代变量,它是自动变量,在这里使用它并不好。

请注意,你所编写的代码可能会占用系统资源(我曾遇到过一次卡住的情况),所以必须适当处理响应。执行$response = $null可能已经足够了,但你仍然需要在循环结束时正确关闭响应。


manojlds -- 感谢您的反馈。非常有用,$response=$null 的方法完美地解决了问题! - Keith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接