问题
I have the following snippet below from my script that's using a WebRequest to ping a list of web/app servers and I'm getting random results based on the order the good/bad servers are listed in the server list.
For example, if the bad servers (where I get back a code of 404 or 503) are listed first in the list then my script seems to report accurately. However, if the good server (which gets back a status = "OK") is listed first then my results are inaccurate.
Here is my code snippet:
$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!!!"
}
}
Here is the example server list:
server1 (reports back a 404)
server2 (reports back a 503)
server3 (gets a status = "OK")
And here is the "accurate" cmd output when I run the script:
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.
Now when I re-order the server list where the good server is listed first, like so:
server3 (gets a status = "OK")
server1 (reports back a 404)
server2 (reports back a 503)
I get inaccurate results where server 1 and server 2 are getting reported as OK:
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.
Why am I getting mixed results based on how the servers are listed?
Thanks in advance!
回答1:
It is because the the WebRequest
raises exception on unsuccessful attempts and $response
doesn't really get set in the cases where you get 503
, 404
etc. When you do get a success, response is set to, well, the response ( with status code being OK), but if the next server raises a 404, say, response would still be the OK state because the WebRequest only raises an exception and doesn't assign anything to $response. You might want to trap
(or try catch
) the exception and handle the success or failure there or set $response
to null in each iteration of the loop:
foreach($server in $serverlist){
$response=$null
...
Also, don't use $_
as the iteration variable, it is automatic variable and is not good form using it here.
Note that what yo have written also might use up system resources, ( it hung once for me), so dispose off the response appropriately. $response = $null
might be enough, but you may still have to close the response properly at end of loop.
回答2:
You might need to close your connection:
$response.Close()
http://msdn.microsoft.com/en-us/library/system.net.webresponse.close(v=vs.90).aspx
I would write it like this:
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
}
}
}
来源:https://stackoverflow.com/questions/9090849/random-webrequest-results-with-powershell