为特定设备循环 IP 的更有效方式
More efficient way of looping through IPs for specific devices
我有以下代码。 IT 或多或少起作用。就挂在离线 IP 上而言,它似乎很慢。
所以我的问题是这样的。
遍历 IP 进行快速 ping,然后遍历实时 IP 的理想方式是吗?
另一个想法是提取设备类型,但由于这些是 phone,您不能像使用计算机那样使用 WMI- 功能。
我的最终目标是 运行 脚本并强制重启网络上的每个 VoIP phone。
$ping = new-object system.net.networkinformation.ping
1..255 | foreach { $IPS = "192.168.2.$_"
$Res = $ping.send($IPS)
if ($Res.Status -eq "Success")
{
$user = 'admin'
$pass = 'admin'
$pair = "$($user):$($pass)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$basicAuthValue = "Basic $encodedCreds"
$Headers = @{
Authorization = $basicAuthValue
}
$URL = "http://"+$IPS+"/servlet?key=Reboot"
Invoke-WebRequest -Uri $URL -Headers $Headers
}
}
更新
偶然发现 Powershell Workflows 作为 运行 并行作业的替代方案。
workflow Restart-Phones {
Param( [string]$Phones )
foreach -parallel ($phone in $phones) {
sequence {
$result = Test-Connection $Phone -Count 1 -Quiet
if ($result) {
$user = 'admin'
$pass = 'admin'
$pair = "$($user):$($pass)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$basicAuthValue = "Basic $encodedCreds"
$Headers = @{
Authorization = $basicAuthValue
}
$URL = "http://"+$IPS+"/servlet?key=Reboot"
Invoke-WebRequest -Uri $URL -Headers $Headers
}
}
}
}
$Phones = 1..255 | % { "192.168.2.$_" }
Restart-Phones $Phones
原创
您可以尝试这样的操作(注意:我没有 运行 全部)。这个想法是您将创建一个 powershell 作业 运行 为您要调用的每个 $IP 创建一个单独的 $RebootScript 实例。这样一来,您就不会被每个无响应的 ping 所阻碍,而只是脚本的那个实例。
$RebootScript = {
Param($IP)
$ping = new-object system.net.networkinformation.ping
$res = $ping.send($IP)
if ($res.Status -eq "Success") {
$user = 'admin'
$pass = 'admin'
$pair = "$($user):$($pass)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$basicAuthValue = "Basic $encodedCreds"
$Headers = @{
Authorization = $basicAuthValue
}
$URL = "http://"+$IPS+"/servlet?key=Reboot"
Invoke-WebRequest -Uri $URL -Headers $Headers
}
}
$jobs = @() #Empty array
1..255 | foreach {
$IP = "192.168.2.$_"
$jobs += Start-Job -ScriptBlock $RebootScript -ArgumentList $IP
}
# Wait until all jobs are finished.
Get-Job | Wait-Job
# Get and display jobs.
Get-Job | Receive-Job
我不确定 ping 对象,但您可以使用 Test-Connection cmdlet 将 ping 计数限制为 1。我使用 Measure-Command 来测试差异,它似乎有所帮助。但是,您需要将条件更改为 ($res.statuscode -contains 0)
Test-Connection -ComputerName $IP -Count 1 -ErrorAction SilentlyContinue
终于找到了一个似乎可以正常工作的解决方案:
1..255 | %{
$IP = "192.168.2.$_"
If (Test-Connection -count 1 -comp $IP -quiet) {
$user = 'admin'
$pass = 'admin'
$pair = "$($user):$($pass)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$basicAuthValue = "Basic $encodedCreds"
$Headers = @{
Authorization = $basicAuthValue
}
$URL = "http://"+$IP+"/servlet?key=Reboot"
Invoke-WebRequest -Uri $URL -Headers $Headers
}
}
我有以下代码。 IT 或多或少起作用。就挂在离线 IP 上而言,它似乎很慢。
所以我的问题是这样的。
遍历 IP 进行快速 ping,然后遍历实时 IP 的理想方式是吗?
另一个想法是提取设备类型,但由于这些是 phone,您不能像使用计算机那样使用 WMI- 功能。
我的最终目标是 运行 脚本并强制重启网络上的每个 VoIP phone。
$ping = new-object system.net.networkinformation.ping
1..255 | foreach { $IPS = "192.168.2.$_"
$Res = $ping.send($IPS)
if ($Res.Status -eq "Success")
{
$user = 'admin'
$pass = 'admin'
$pair = "$($user):$($pass)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$basicAuthValue = "Basic $encodedCreds"
$Headers = @{
Authorization = $basicAuthValue
}
$URL = "http://"+$IPS+"/servlet?key=Reboot"
Invoke-WebRequest -Uri $URL -Headers $Headers
}
}
更新
偶然发现 Powershell Workflows 作为 运行 并行作业的替代方案。
workflow Restart-Phones {
Param( [string]$Phones )
foreach -parallel ($phone in $phones) {
sequence {
$result = Test-Connection $Phone -Count 1 -Quiet
if ($result) {
$user = 'admin'
$pass = 'admin'
$pair = "$($user):$($pass)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$basicAuthValue = "Basic $encodedCreds"
$Headers = @{
Authorization = $basicAuthValue
}
$URL = "http://"+$IPS+"/servlet?key=Reboot"
Invoke-WebRequest -Uri $URL -Headers $Headers
}
}
}
}
$Phones = 1..255 | % { "192.168.2.$_" }
Restart-Phones $Phones
原创
您可以尝试这样的操作(注意:我没有 运行 全部)。这个想法是您将创建一个 powershell 作业 运行 为您要调用的每个 $IP 创建一个单独的 $RebootScript 实例。这样一来,您就不会被每个无响应的 ping 所阻碍,而只是脚本的那个实例。
$RebootScript = {
Param($IP)
$ping = new-object system.net.networkinformation.ping
$res = $ping.send($IP)
if ($res.Status -eq "Success") {
$user = 'admin'
$pass = 'admin'
$pair = "$($user):$($pass)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$basicAuthValue = "Basic $encodedCreds"
$Headers = @{
Authorization = $basicAuthValue
}
$URL = "http://"+$IPS+"/servlet?key=Reboot"
Invoke-WebRequest -Uri $URL -Headers $Headers
}
}
$jobs = @() #Empty array
1..255 | foreach {
$IP = "192.168.2.$_"
$jobs += Start-Job -ScriptBlock $RebootScript -ArgumentList $IP
}
# Wait until all jobs are finished.
Get-Job | Wait-Job
# Get and display jobs.
Get-Job | Receive-Job
我不确定 ping 对象,但您可以使用 Test-Connection cmdlet 将 ping 计数限制为 1。我使用 Measure-Command 来测试差异,它似乎有所帮助。但是,您需要将条件更改为 ($res.statuscode -contains 0)
Test-Connection -ComputerName $IP -Count 1 -ErrorAction SilentlyContinue
终于找到了一个似乎可以正常工作的解决方案:
1..255 | %{
$IP = "192.168.2.$_"
If (Test-Connection -count 1 -comp $IP -quiet) {
$user = 'admin'
$pass = 'admin'
$pair = "$($user):$($pass)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$basicAuthValue = "Basic $encodedCreds"
$Headers = @{
Authorization = $basicAuthValue
}
$URL = "http://"+$IP+"/servlet?key=Reboot"
Invoke-WebRequest -Uri $URL -Headers $Headers
}
}