我编写了一个ScriptBlock,它将post文件上传到自定义http服务器并将响应保存到磁盘。它旨在用于测试所述服务器,除了检查正确的响应外,我还想并行运行它以加载服务器。
ScriptBlock中的代码是作为单独的ps1脚本构建的。然后,我使用Start-Job
将其移植到框架脚本中,以管理作业并最终呈现总体结果。
不幸的是,移植后就不起作用了。
症状是使用Start-Job
作业永远不会完成。为了测试,我已经切换到Invoke-Command
。一个简单的Invoke-Command
可以工作,InvokeCommand -AsJob
不能。
:
Invoke-Command -Scriptblock $ScriptBlock -ArgumentList $Name,"C:ProjectsDCACCITServiceBroker4Javaeclipse-workspaceXFAWorkertestdata","P7-T"
不工作:
Invoke-Command -AsJob -Computer localhost -Scriptblock $ScriptBlock -ArgumentList $Name,"C:ProjectsDCACCITServiceBroker4Javaeclipse-workspaceXFAWorkertestdata","P7-T"
Start-Job -Name $Name -ScriptBlock $Scriptblock -ArgumentList $Name,"C:ProjectsDCACCITServiceBroker4Javaeclipse-workspaceXFAWorkertestdata","P7-T"
正在使用的ScriptBlock相当长。它首先声明Parameters:
$Scriptblock = {
Param (
[string]$JobName,
[string]$path,
[string]$BASEJOBNAME
)
和进一步使用HttpWebRequest和其他一些。net类:
$url = "http://localhost:8081/fillandflatten"
[System.Net.HttpWebRequest] $req = [System.Net.WebRequest]::create($url)
...
$xfabuffer = [System.IO.File]::ReadAllBytes("$path$BASEJOBNAME.xml")
...
$header = "--$boundary`r`nContent-Disposition: form-data; name=`"xfa`"; filename=`"xfa`"`r`nContent-Type: text/xml`r`n`r`n"
$buffer = [Text.Encoding]::ascii.getbytes($header)
...
[System.Net.httpWebResponse] $res = $req.getResponse()
如前所述,当使用Start-Job
或Invoke-Command -AsJob
时,启动的子作业将永远保持在Running
状态。
什么会导致这种行为?可以用什么来调试它?如果有一些错误,我可以强制终止子作业,并告诉我它不喜欢什么?
我在Windows XP上使用PowerShell 2.0。
在我提出的框架中,我做了Start-Job
(目前只是其中一个,但我计划在压力测试中增加这个数字)。然后我有一个循环等待它们全部终止:
do {
$Jobs = @(Get-Job | Where { $_.State -eq "Running" -and $_.Name.StartsWith($BASEJOBNAME) });
$n = $Jobs.Count
if ($n -gt 0)
{
Log -message "Waiting for $n jobs to finish..."
Get-Job | Where { $_.Name.StartsWith($BASEJOBNAME) } | Format-Table -AutoSize -Property Id,Name,State,HasMoreData,Location
start-Sleep -Seconds 3
}
} until ($n -eq 0)
生成如下形式的输出:
2014-08-01 18:58:52 - Waiting for 1 jobs to finish...
Id Name State HasMoreData Location
-- ---- ----- ----------- --------
2 XFA001 Running True localhost
永远。
一个完整的最小测试用例是:
# Code for the Jobs:
$Scriptblock = {
[System.Net.HttpWebRequest] $req = [System.Net.WebRequest]::create("http://locahost/index.html")
return "done"
}
# Start a job. Three variants, The Job-based ones hang.
# Invoke-Command -Scriptblock $ScriptBlock
#Invoke-Command -AsJob -Computer localhost -Scriptblock $ScriptBlock
$Job = Start-Job -Name $Name -ScriptBlock $Scriptblock
## The rest of the code is only applicable for the Start-Job-Variant
# Wait for all Jobs to finish
do {
$Jobs = @(Get-Job | Where { $_.State -eq "Running" });
$n = $Jobs.Count
if ($n -gt 0)
{
Write-Host "Waiting for $n jobs to finish..."
Get-Job | Format-Table -AutoSize -Property Id,Name,State,HasMoreData
Start-Sleep -Seconds 3
}
} until ($n -eq 0)
# Get output from all jobs
$Data = ForEach ($Job in (@(Get-Job | Where { $_.Name.StartsWith($BASEJOBNAME) } ))) {
Receive-Job $Job
}
# Clean out all jobs
ForEach ($Job in (@(Get-Job | Where { $_.Name.StartsWith($BASEJOBNAME) } ))) {
Remove-Job $Job
}
# Dump output
Write-Host "Output data:"
$Data | Format-Table
Write-Host ""
这个适合我。如果我注释掉创建WebRequest对象的行,它就会工作。
谢谢。
运行Get-Job时,作业的"HasMoreData"属性是否为"True" ?
如果是,检查作业输出:
Receive-Job <JobName or JobID> -Keep