Invoke-WebRequest работает после того, как сервер недоступен

Я использую Invoke-WebRequest в сценарии SCOM PowerShell для периодического мониторинга доступности URI. Мой сценарий довольно прост (так как я очень мало знаю о PS:-)):

$scomapi = new-object -comObject "MOM.ScriptAPI"
$scompb = $scomapi.CreatePropertyBag()
$fullHostName = "https://" + <full path to monitored web endpoint>
$result = Invoke-WebRequest $fullHostName
if($result.content) {
    $scompb.AddValue("ConfigurationReachable",$true);
} else {
    $scompb.AddValue("ConfigurationReachable",$false);
}           
$scomapi.AddItem($scompb) 
$scomapi.ReturnItems()

Чтобы протестировать этот скрипт, я сделал ручные изменения в hosts файл на клиенте с агентом SCOM, где я хочу сделать мониторинг. Интересно, что сценарий успешно извлекает конечную точку сети даже после того, как хост недоступен (это было проверено путем проверки связи с этой машины).

Я сделал несколько дальнейших тестов прямо из командной строки, и ничего не изменилось. Хотя у меня нет пинга на удаленный адрес, Invoke-WebRequest все еще удается и получает веб-страницу. Так что я здесь не так делаю?

3 ответа

Решение

Без тестирования, я думаю, это DNS-кеширование.

Сеанс powershell, вероятно, кэширует ip при первом запросе и игнорирует обновление вашего hosts-файла (просто использует старый рабочий ip).

Попробуйте запустить скрипт до и после отсоединения сетевого адаптера / кабеля, чтобы имитировать сбой сервера.

ОБНОВЛЕНИЕ: То, что я пытаюсь сказать выше, это то, что сценарий будет отлично работать, если серверы недоступны, но ваша симуляция с использованием файла hosts дает "ложноположительный" (так что игнорируйте результаты).

Если вам действительно нужно протестировать скрипт с редактированием файла hosts, отключите кеш.Net dns в сеансе, добавив следующую строку в начале вашего скрипта:

[System.Net.ServicePointManager]::DnsRefreshTimeout = 0

За обсуждение в комментариях проблема кешируется; только проблема не в том, что кешируется IP (по крайней мере, не единственная проблема); содержимое также кэшируется; поэтому вместо того, чтобы заходить на веб-сервер, чтобы получить ваш ресурс, система обманывает и получает его локально. Вы можете предотвратить это, добавив -Headers @{"Cache-Control"="no-cache"} на ваш invoke-webrequest,

Смотрите пример тестового скрипта ниже; попробуйте бегать с и без cache-control заголовок до и после настройки файла hosts.

cls

$urlHost = 'server.mydomain.com'
$endpointUrl = ("https://{0}/path/to/resource.jpg" -f $urlHost)

#can be set once at the start of the script
[System.Net.ServicePointManager]::DnsRefreshTimeout = 0

#I don't have Clear-DnsClientCache; but the below should do the same thing
#Should be called inside any loop before the invoke-webrequest to ensure
#flush your machine's local dns cache each time
ipconfig /flushdns

#prove that our hosts update worked:
#optional, but will help in debugging
Test-Connection $urlHost -Count 1 | select ipv4address

#ensure we don't have a remembered result if invoke-request is in a loop
$result = $null
#make the actual call
#NB: -headers parameter takes a value telling the system not to get anything
#from the cache, but rather to send the request back to the root source.
$result = Invoke-WebRequest $endpointUrl -Headers @{"Cache-Control"="no-cache"}

#output the result; 200 means all's good (google http status codes for info on other values)
("`nHTTP Status Code: {0}`n" -f $result.StatusCode)

#output actual result; optional, but may be useful to see what's being returned (e.g. is it your page/image, or a 404 page / something unexpected
$result

Я знаю, что это старый, но на всякий случай это кому-то поможет:

Я столкнулся с подобной проблемой, и добавление "-Disable KeepAlive" решило ее для меня.

Другие вопросы по тегам