【发布时间】:2014-05-12 16:10:57
【问题描述】:
背景:
我想运行一个测试,并在它运行时收集 CPU 利用率。基本上,当我开始测试时,我还想开始收集 CPU 利用率数据,在测试结束时,我还想停止收集 CPU 利用率数据(然后取平均值)。
在 Win7 上使用 PowerShell 3
方法:
在测试开始时,我添加了一个启动后台作业的函数。后台作业执行一个脚本块,该脚本块运行一个“while ($true)”循环,该循环收集平均 CPU 利用率并将其保存到文件中。在测试结束时,我读取文件,平均收集的数据并停止并删除作业。
问题:
对于当前的方法,脚本块并不总是被执行,也不会收集新数据。如果我多次运行测试,脚本块会被执行(在其中一次运行中)——我想不出任何相关的东西或这种行为。如果我在测试中的任何地方使用断点,脚本块也总是会被执行。
想不出别的办法。
需要的答案:
1. 为什么脚本块没有被执行?以及如何让它执行?
2. 是否有其他方法可以在测试期间收集资源数据?
请注意,代码已通过各种尝试和失败运行,不再“漂亮”。
代码:
function Start-ResourceMonitor
{
param()
$avg=@()
$timestamp = Get-Date -Format o | foreach {$_ -replace ":", "."}
$compName=$env:COMPUTERNAME
$myFilePath = Join-Path -path $env:TEMP -childpath .\temp_$timestamp.txt
$scriptBlock = {
$avgSB = $args[0]
$timestampSB = $args[1]
while ($true) {
$avgSB += Get-WmiObject win32_processor -computername $args[2] | Measure-Object -property LoadPercentage -Average | Foreach {$_.Average}
$avgSB | Out-File -FilePath $args[3] -Force
start-sleep -Milliseconds 500
}
}
$res = start-job -RunAs32 -Name 'MyJob' -ScriptBlock $scriptBlock -ArgumentList @($avg,$timestamp,$compName,$myFilePath)
while (($res.State -ne 'Running') -or (-not (Test-Path $myFilePath))){
start-sleep -Milliseconds 500
}
}
[other test functions]
function Stop-ResourceMonitor
{
param()
Stop-Job -Name MyJob
$testFN = Get-ChildItem -Path $env:TEMP -Filter "temp*.txt" | sort LastWriteTime -Descending | select -First 1
$global:CPU_Average = get-content -path $testFN.FullName
$global:CPU_Average | Measure-Object -Average | select -ExpandProperty Average | Write-Host
Remove-Job -Name MyJob
}
【问题讨论】:
-
我猜测
Job已添加,但尚未开始执行(即State尚未更改为Running)。创建Job时,您将放弃处理Scriptblock的调度。由于您依赖于等到Job开始执行,您难道不能像Start-ResourceMonitor中的最后一行那样循环休眠直到Job的State更改为Running? -
@robert.westerlund 我已经尝试了您的建议,但得到了相同的结果。出于调试目的(仅限本地版本),我在停止之前在 Stop-ResourceMonitor 中输出作业状态 - 到目前为止,在我的所有运行中,状态一直在运行。
-
是的,但是
Job可能在您停止它之前开始运行,即在您执行实际测试之后。如果您在执行实际测试之前输出作业的状态,我猜它不在Running状态。同样,我只是在猜测,因为我不确定您如何确定“脚本块并不总是被执行”。 -
@robert.westerlund 澄清 - 除了我自己的调试版本状态输出之外,我还按照您的建议在 Start-ResourceMonitor 中添加了睡眠循环,并得到了相同的结果。确定脚本块未执行的一种方法是检查 C:\TEMP 文件夹中是否有应为每次运行创建的新文件。
-
只是为了确保我理解,您尝试包含的睡眠循环是否放在紧跟
$res = Start-Job ...之后的行上,并且看起来类似于while ($res.State -ne 'Running'){ Start-Sleep -Milliseconds 500 }?另外,您的测试过程运行多长时间?我猜它至少运行了几秒钟,这个猜测正确吗?请记住,Get-WmiObject -ComputerName ...也可能需要很短的时间才能获得响应,因此,如果测试在Job开始之前完成或比Get-WmiObject调用完成更快,您将不会得到写入文件。
标签: powershell cpu-usage powershell-3.0 scriptblock