我有2个功能,一个用于获取数据,另一个用于输出数据。将这些内容拆分为允许“刷新”,而不必再次请求静态信息。
我希望Get-AllAP函数发出请求并存储数据。
我希望Show-APAll函数获取该数据并输出。
这样做的原因是在“刷新”上,我们可以运行Show-APAll,这只会从第一个请求输出数据,而不是发出整个其他请求。
function Get-AllAP {
$functionName = $MyInvocation.MyCommand
Write-Verbose "Function Start: Get-AllAP"
Write-Log "Get-AllAp started for Store $Store" -Level INFO -logfile $logFile
Write-Host "Getting all Access Points in Store $Store. This can take a moment."
Write-Verbose "Getting all APs for Store $Store"
$storeApReq = "https://cpist/webacs/api/v3/data/AccessPointDetails.json?.group=$Store"
Write-Verbose "Making request to $storeApReq"
$global:apIdListReq = Invoke-RestMethod -Uri $storeApReq -Method Get -ContentType 'application/json' -Headers @{ Authorization = $auth }
Write-Log "Making Get request to $storeApReq" -Level INFO -logfile $logFile
$global:apIdList = $apIdListReq.queryResponse.entityId
$global:apIdCount = $apIdListReq.queryResponse."@count"
$global:controllerName = $apData.unifiedApInfo.controllerName
$global:apIdURL = $apIdListReq.queryResponse.entityId
$global:apURLs = $apIdListReq.queryResponse.entityId | ForEach-Object -MemberName '@url'
## Create array object of all aps on site
Write-Verbose "Creating Access Point loop"
$global:apArray = New-Object System.Collections.ArrayList
Write-Host "Getting status on Access Points: " -NoNewLine
## Begin looping
$global:apLoop = foreach ($apURL in $apURLs) {
$apFullReq = Invoke-RestMethod -Uri $apURL'.json' -Method Get -ContentType 'application/json' -Headers @{ Authorization = $auth }
$global:allApData = $apFullReq.queryResponse.entity.accessPointDetailsDTO
## Store our data
$global:apStatus =$allApData.status
$global:apName = $allApData.name
$global:apPing = $allApData.reachabilitystatus
$global:controllerName = $allApData.unifiedApInfo.controllerName
$global:switch = $allApData.cdpNeighbors.cdpNeighbor[0].neighborName
$global:switchPort = $allApData.cdpNeighbors.cdpNeighbor[0].neighborPort
$global:location = $allApData.locationHierarchy
$global:clientCount = $allApData.clientCount
## Watch for errors in loop
Write-Host "$apName " -NoNewline
## Output apName to array for use later
$apArray.Add($apName)
Write-Log "$apName discovered with $clientCount devices connected." -Level DEBUG -logfile $logFile
}
}
此函数查询API,并获取有关我们稍后要使用的AP的信息。接下来,它将引用Show-APAll
来显示此数据。
Function Show-APAll {
$functionName = $MyInvocation.MyCommand
Write-Log "Show-APAll started for Store $Store" -Level INFO -logfile $logFile
Write-Verbose "Function start: Show-APAll"
Clear
Write-Host " "
Write-Host '-------------------------------------------' -Foregroundcolor "DarkCyan"
Write-Host " All Access Points For Store $Store"
Write-Host '-------------------------------------------' -Foregroundcolor "DarkCyan"
foreach ($apName in $apArray) {
## Print to log for debugging
Write-Log "$apName discovered with $clientCount devices connected." -Level DEBUG -logfile $logFile
## Output data for user
Write-Host " "
Write-Host "AP Name: $apName"
if ($apPing -eq 'UNREACHABLE') {
Write-Host "AP is Offline" -Foregroundcolor "Red"
} else {
Write-Host "AP is Online" -ForegroundColor "Green"
}
if ($apStatus -eq 'Critical') {
Write-Host "AP Problem Level:$apStatus" -Foregroundcolor "Red"
} else {
Write-Host "AP Problem Level: $apStatus" -ForegroundColor "Green"
}
Write-Host "Clients Connected: $clientCount"
Write-Host "Location: $location"
Write-Host "Switch Port: $switchPort on $switch"
}
Management-AfterAll
}
正如您确定的那样,这里发生的事情是只有$apName
是唯一的,而其余数据作为最后一个要循环通过的对象存储在变量中。以下是一些日志,它们准确显示了$clientCount
发生的情况。
日志输出:
2018/09/04 08:39:42 INFO Making Get request to https://cpist/webacs/api/v3/data/AccessPointDetails.json?.group=0026 Function: Get-AllAP User: admin-dksc104694 2018/09/04 08:39:42 DEBUG 0026AP4 discovered with 1 devices connected. Function: Get-AllAP User: admin-dksc104694 2018/09/04 08:39:43 DEBUG 0026AP7 discovered with 3 devices connected. Function: Get-AllAP User: admin-dksc104694 2018/09/04 08:39:43 DEBUG 0026AP8 discovered with 0 devices connected. Function: Get-AllAP User: admin-dksc104694 2018/09/04 08:39:43 DEBUG 0026AP3 discovered with 1 devices connected. Function: Get-AllAP User: admin-dksc104694 2018/09/04 08:39:44 DEBUG 0026AP9 discovered with 0 devices connected. Function: Get-AllAP User: admin-dksc104694 2018/09/04 08:39:44 DEBUG 0026AP1 discovered with 9 devices connected. Function: Get-AllAP User: admin-dksc104694 2018/09/04 08:39:44 DEBUG 0026AP6 discovered with 1 devices connected. Function: Get-AllAP User: admin-dksc104694 2018/09/04 08:39:44 DEBUG 0026AP10 discovered with 1 devices connected. Function: Get-AllAP User: admin-dksc104694 2018/09/04 08:39:45 DEBUG 0026AP2 discovered with 0 devices connected. Function: Get-AllAP User: admin-dksc104694 2018/09/04 08:39:45 DEBUG 0026AP5 discovered with 1 devices connected. Function: Get-AllAP User: admin-dksc104694 2018/09/04 08:39:45 INFO Show-APAll started for Store 0026 Function: Show-APAll User: admin-dksc104694 2018/09/04 08:39:45 DEBUG 0026AP4 discovered with 1 devices connected. Function: Show-APAll User: admin-dksc104694 2018/09/04 08:39:45 DEBUG 0026AP7 discovered with 1 devices connected. Function: Show-APAll User: admin-dksc104694 2018/09/04 08:39:45 DEBUG 0026AP8 discovered with 1 devices connected. Function: Show-APAll User: admin-dksc104694 2018/09/04 08:39:45 DEBUG 0026AP3 discovered with 1 devices connected. Function: Show-APAll User: admin-dksc104694 2018/09/04 08:39:45 DEBUG 0026AP9 discovered with 1 devices connected. Function: Show-APAll User: admin-dksc104694 2018/09/04 08:39:45 DEBUG 0026AP1 discovered with 1 devices connected. Function: Show-APAll User: admin-dksc104694 2018/09/04 08:39:45 DEBUG 0026AP6 discovered with 1 devices connected. Function: Show-APAll User: admin-dksc104694 2018/09/04 08:39:45 DEBUG 0026AP10 discovered with 1 devices connected. Function: Show-APAll User: admin-dksc104694 2018/09/04 08:39:45 DEBUG 0026AP2 discovered with 1 devices connected. Function: Show-APAll User: admin-dksc104694 2018/09/04 08:39:45 DEBUG 0026AP5 discovered with 1 devices connected. Function: Show-APAll User: admin-dksc104694
$clientCount
的响应值在Get-AllAp
中很好,但是仅最后一个要循环的AP的值可用。我确实知道为什么会这样,因为显然变量在给定的时间内只能有一个赋值,但是我不确定如何解决此问题而不会造成混乱。
我尝试了很多事情,包括将数据添加到$apArray
,但这在输出中造成混乱,只是将数组中的位置返回为整数。有人可以指出我正确的方向吗?
答案1编辑:
Function Get-AllAP {
$functionName = $MyInvocation.MyCommand
Write-Verbose "Function Start: Get-AllAP"
Write-Log "Get-AllAp started for Store $Store" -Level INFO -logfile $logFile
Write-Host "Getting all Access Points in Store $Store. This can take a moment."
Write-Verbose "Getting all APs for Store $Store"
$storeApReq = "https://cpist/webacs/api/v3/data/AccessPointDetails.json?.group=$Store"
Write-Verbose "Making request to $storeApReq"
$Global:apIdListReq = Invoke-RestMethod -uri $storeApReq -method Get -ContentType 'application/json' -headers @{ Authorization = $auth }
Write-Log "Making Get request to $storeApReq" -Level INFO -logfile $logFile
$apIdList = $apIdListReq.queryResponse.entityId
$apIdCount = $apIdListReq.queryResponse."@count"
$controllerName = $apData.unifiedApInfo.controllerName
$apIdURL = $apIdListReq.queryResponse.entityId
$apURLs = $apIdListReq.queryResponse.entityId | ForEach-Object -MemberName '@url'
## Create array object of all aps on site
Write-Verbose "Creating Access Point loop"
$Global:apArray = New-Object System.Collections.ArrayList
Write-Host "Getting status on Access Points: " -NoNewLine
## Begin looping
foreach ($apURL in $apURLs) {
$apFullReq = Invoke-RestMethod -Uri "${apURL}.json" -Method Get -ContentType 'application/json' -Headers @{Authorization = $auth}
$allApData = $apFullReq.queryResponse.entity.accessPointDetailsDTO
$apArray = New-Object -Type PSObject -Property @{
'apStatus' = $allApData.status
'apName' = $allApData.name
'apPing' = $allApData.reachabilitystatus
'controllerName' = $allApData.unifiedApInfo.controllerName
'switch' = $allApData.cdpNeighbors.cdpNeighbor[0].neighborName
'switchPort' = $allApData.cdpNeighbors.cdpNeighbor[0].neighborPort
'location' = $allApData.locationHierarchy
'clientCount' = $allApData.clientCount
}
}
}
这确实有助于使数据与PS友好,并且我可以输出数据,但这不能解决问题中概述的问题。
答案 0 :(得分:2)
停止对所有内容使用全局变量。从REST响应中创建自定义对象,然后将其输出到函数中,然后将函数输出收集到调用方作用域中的变量中。
function Get-AllAP {
...
$apIdList = $apIdListReq.queryResponse.entityId
$apIdCount = $apIdListReq.queryResponse."@count"
$controllerName = $apData.unifiedApInfo.controllerName
$apIdURL = $apIdListReq.queryResponse.entityId
$apURLs = $apIdListReq.queryResponse.entityId | ForEach-Object -MemberName '@url'
...
foreach ($apURL in $apURLs) {
$apFullReq = Invoke-RestMethod -Uri "${apURL}.json" -Method Get -ContentType 'application/json' -Headers @{Authorization = $auth}
$allApData = $apFullReq.queryResponse.entity.accessPointDetailsDTO
New-Object -Type PSObject -Property @{
'apStatus' = $allApData.status
'apName' = $allApData.name
'apPing' = $allApData.reachabilitystatus
'controllerName' = $allApData.unifiedApInfo.controllerName
'switch' = $allApData.cdpNeighbors.cdpNeighbor[0].neighborName
'switchPort' = $allApData.cdpNeighbors.cdpNeighbor[0].neighborPort
'location' = $allApData.locationHierarchy
'clientCount' = $allApData.clientCount
}
}
}
$apArray = Get-AllAP
向函数Show-AllAP
添加参数,并将变量$apArray
作为函数的参数传递:
function Show-AllAP {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[array]$apList
)
...
foreach ($ap in $apList) {
Write-Host ('AP Name: {0}' -f $ap.apName)
...
}
...
}
Show-AllAP $apArray
重点不是完全避免全局变量,而是避免在嵌套上下文中修改(甚至使用)全局变量。定义明确的界面使读者可以清楚地知道哪些信息(来自代码的其余部分)进入了该函数,以及该函数返回了哪些数据(尽管PowerShell当然承认后者有些模糊)。嵌套上下文中的全局变量基本上是数据流中的一个辅助渠道,通常会使故障排除更加复杂,尤其是当您的代码库增长时。
将代码封装在函数中的全部目的是提供一种抽象,您可以在其中更改函数的实现以及全局代码(例如重命名全局变量),而又不影响另一个。只要功能接口(参数集和返回的数据)不变,就可以。