【问题标题】:WMI Queries takes longWMI 查询需要很长时间
【发布时间】:2016-08-18 14:04:50
【问题描述】:

我正在查询大约 280 个 XenApp 服务器。这是我的疑问。

$bootupMemory = gwmi -Query "SELECT * FROM Win32_OperatingSystem" -ComputerName $srv
#$cpuLoad      = gwmi -Query "SELECT * FROM Win32_Processor" -ComputerName $srv
#$tSessions    = gwmi -Query "SELECT * FROM Win32_TerminalService" -ComputerName $srv
$ima          = gwmi -Query "SELECT * FROM Win32_Service WHERE name='imaservice'" -ComputerName $srv 
$mfcom        = gwmi -Query "SELECT * FROM Win32_Service WHERE name='mfcom'" -ComputerName $srv
$ctxPrintMgr  = gwmi -Query "SELECT * FROM Win32_Service WHERE name='cpsvc'" -ComputerName $srv
$msmqstatus   = gwmi -Query "SELECT * FROM Win32_Service WHERE name='msmq'" -ComputerName $srv

$cDrive       = gwmi -Query "SELECT * FROM Win32_Logicaldisk WHERE deviceid='c:'" -ComputerName $srv
$dDrive       = gwmi -Query "SELECT * FROM Win32_Logicaldisk WHERE deviceid='d:'" -ComputerName $srv
$loginStatus  = gwmi -Query "SELECT loginsenabled, numberofsessions FROM Metaframe_Server" -Namespace root\citrix -ComputerName $srv
$load         = gwmi -Query "SELECT * FROM Metaframe_Server_loadlevel" -Namespace root\citrix -ComputerName $srv

您能否建议这是否是最佳的,或者我可以对其进行优化。 还如何将超时参数与每个查询合并。这可能吗?

【问题讨论】:

  • WMI,在真正的答案是大量多线程之前,您能做的只有这么多。我有一个荒谬的系统,它将这种事情传播到几台服务器上,每台服务器都有 100 个线程,这样我就可以在合理的时间范围内从几千台服务器中提取数据。你有看过 Start-Job 和朋友吗?
  • start-job 有什么帮助,我的意思是它是否同时在所有 280 台服务器上运行。还帮我回答这个问题:我的代码位于远程文件共享中,start-job 是否需要每个服务器上的本地文件,或者它可以处理远程共享上的脚本。

标签: powershell wmi wql xenapp


【解决方案1】:

针对同一个主机对同一个类运行多个查询肯定不是最优的。您可以通过合并同一类的查询的WHERE 子句来在一定程度上优化您的代码:

SELECT * FROM Win32_Service WHERE name='imaservice' OR name='mfcom' OR name='cpsvc' OR name='msmq'

但是,由于您仍然需要查询几个不同的类,我建议您在远程主机上运行整个代码并将结果作为自定义对象返回:

$result = Invoke-Command -ComputerName $srv -ScriptBlock {
  New-Object -Type PSObject -Property @{
    computername = $env:COMPUTERNAME
    bootupMemory = gwmi -Query "SELECT * FROM Win32_OperatingSystem"
    #cpuLoad      = gwmi -Query "SELECT * FROM Win32_Processor"
    #tSessions    = gwmi -Query "SELECT * FROM Win32_TerminalService"
    ima          = gwmi -Query "SELECT * FROM Win32_Service WHERE name='imaservice'"
    mfcom        = gwmi -Query "SELECT * FROM Win32_Service WHERE name='mfcom'"
    ctxPrintMgr  = gwmi -Query "SELECT * FROM Win32_Service WHERE name='cpsvc'"
    msmqstatus   = gwmi -Query "SELECT * FROM Win32_Service WHERE name='msmq'"
    cDrive       = gwmi -Query "SELECT * FROM Win32_Logicaldisk WHERE deviceid='c:'"
    dDrive       = gwmi -Query "SELECT * FROM Win32_Logicaldisk WHERE deviceid='d:'"
    loginStatus  = gwmi -Query "SELECT loginsenabled, numberofsessions FROM Metaframe_Server" -Namespace root\citrix
    load         = gwmi -Query "SELECT * FROM Metaframe_Server_loadlevel" -Namespace root\citrix
  }
}

在单独的job 中为每个服务器运行Invoke-Command 以并行运行查询,从而减少整体处理时间。

Start-Job -ScriptBlock {
  Invoke-Command -ComputerName $args[0] -ScriptBlock {
    New-Object ...
  }
} -ArgumentList $srv

Get-Job | Wait-Job | Receive-Job

或(正如 Mathias 在 cmets 中建议的那样)

Invoke-Command -ComputerName $srv -AsJob -ScriptBlock {
  New-Object ...
}

Get-Job | Wait-Job | Receive-Job

【讨论】:

  • Invoke-Command 甚至有一个-AsJob 开关,让生活更轻松!
  • 我正在尝试使用 -asjob 运行调用命令,但我没有得到任何结果 $serversRaw = qfarm /load $hostnames = for($i=3;$i -lt $ serversRaw.length; $i++) { ($serversRaw[$i] -split " ")[0] } if (($result = Read-host "输入 c: 或 D: [默认为 C:]") - eq '') { $drive = "C:"} else {$drive = $result } icm -computer $hostnames { gwmi -cl win32_logicaldisk | ? { $_.deviceid -eq $drive } |选择大小、可用空间、pscomputername } -asjob #$x |接收工作接收工作
  • @user183932 如果您有新问题或后续问题:请发布新问题。如果您发现我的回答有助于解决此问题中描述的问题:请考虑accepting it
猜你喜欢
  • 1970-01-01
  • 2016-02-02
  • 2018-01-09
  • 2015-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多