我正在构建一个执行 http 请求的脚本,以便“唤醒”一些 asp.net 应用程序。
以下脚本可以运行,但是是同步的:
function WakeUp([string] $url)
{
Write-Host "Waking up $url ..." -NoNewLine
$client = new-object system.net.WebClient
$client.UseDefaultCredentials = $true
$null = $client.OpenRead($url)
$client.Dispose()
Write-Host " Ok"
}
# Run your code that needs to be elevated here
@(
"http://app1/",
"http://app2/",
"http://app3/"
) | % { WakeUp $_ }
我想改进这个脚本以避免目标站点被唤醒。事实上,对的调用会OpenRead
等待答案后再返回。
我尝试过使用,但是在实际发出请求之前就发生了OpenReadAsync
调用,并且目标应用程序尚未被唤醒。Dispose
我有什么选择?
[编辑]根据 Andy Arismendi 的建议,我的脚本现在是:
$WakeUp = {
Param ([string] $url)
try
{
Write-Output "Waking up $url ..."
$client = new-object system.net.WebClient
$client.UseDefaultCredentials = $true
$null = $client.OpenRead($url)
$client.Dispose()
Write-Output "$url Ok"
} catch {
Write-Error $_
throw $_
}
}
$jobs = @()
# Run your code that needs to be elevated here
@(
"http://app1/",
"http://app2/",
"http://app3/"
) | % {
$jobs += Start-Job -ScriptBlock $WakeUp -ArgumentList $_
}
Receive-Job -Job $jobs -Keep
Wait-Job -Job $jobs
这似乎按预期工作,但我失去了写入主机。有什么想法吗?
答案1
后台作业可以使您的工作流程异步。
将唤醒函数转换为脚本块:
$WakeUp = { ([string] $url) try { # Processing... } catch { throw $_ } }
对于每个 URL,将脚本块作为后台作业启动。
@( "http://app1" # More... ) | % { Start-Job -ScriptBlock $WakeUp -ArgumentList $_ }
查看我的回答从另一个问题了解如何从后台作业接收数据并检测哪些失败了。
更新
这解决了您的版本中未接收输出的问题。您需要使用Wait-Job
beforeReceive-Job
来允许它们完成,因为它们是异步运行的。
$WakeUp = {
param ([string] $url)
try {
Write-Output "Waking up $url ..."
Start-Sleep -Seconds 3
if ($url -eq "http://app2/") {
throw ($url + " failed")
}
Write-Output "$url Ok"
} catch {
throw $_
}
}
$jobs = @()
# Run your code that needs to be elevated here
@(
"http://app1/",
"http://app2/",
"http://app3/"
) | % {
$jobs += Start-Job -ScriptBlock $WakeUp -ArgumentList $_
}
Wait-Job -Job $jobs | Out-Null
Receive-Job -Job $jobs -Keep