英文:
Append to array in powershell job
问题
我找到了一段代码,可以一次性对所有系统进行ping,比其他工作示例都要好。这个代码可以逐行处理一个完整的主机文件,并且可以同时ping它们。但是,我该如何将那些正常运行的主机添加到我的$online
数组中呢?我尝试在true
块中添加,但没有起作用。我只是想在某个地方加入$online += $pc
。任何帮助将不胜感激。谢谢。
$online = @()
$pc = Get-Content C:\servers.txt
$pc | ForEach-Object { Test-Connection -ComputerName $_ -Count 1 -AsJob } | Get-Job | Receive-Job -Wait | Select-Object @{Name='ComputerName';Expression={$_.Address}},@{Name='Reachable';Expression={if ($_.StatusCode -eq 0) { $true } else { $false }}} | Where-Object { $_.Reachable -eq $true } | ForEach-Object { $online += $_.ComputerName }
在这个修改后的代码中,我们使用Where-Object
筛选出那些可达的主机,并将它们的名称添加到$online
数组中。
英文:
I was able to find a piece of code that could ping all systems at once, better than any other job examples I've come across. This thing can take an entire file full of hosts, line by line, and ping them all literally at the same time. But how can I add the ones that are up to my $online
array? I tried adding in the true
block but it didn't work. Im simply trying to stick $online += $pc
somewhere. Any help would be appreciated. Thanks.
$online = @()
$pc = Get-Content C:\servers.txt
$pc | ForEach-Object { Test-Connection -ComputerName $_ -Count 1 -AsJob } | Get-Job | Receive-Job -Wait | Select-Object @{Name='ComputerName';Expression={$_.Address}},@{Name='Reachable';Expression={if ($_.StatusCode -eq 0) { $true } else { $false }}} | ft -AutoSize
答案1
得分: 1
以下是您要翻译的内容:
<!-- language-all: sh -->
You can store the result of your jobs and then filter by `Reachable`. I've also simplified your code a bit and added `-AutoRemove` which I consider important to dispose your jobs when done.
$result = Get-Content C:\servers.txt | ForEach-Object {
Test-Connection -ComputerName $_ -Count 1 -AsJob
} | Receive-Job -Wait -AutoRemoveJob | ForEach-Object {
[pscustomobject]@{
ComputerName = $_.Address
Reachable = $_.StatusCode -eq 0
}
}
$online = $result | Where-Object Reachable
# if you want just the `ComputerName` values, you can do
$online = $result | Where-Object Reachable | ForEach-Object ComputerName
# or easier, using member-access enumeration and `.Where` method
$online = $result.Where{ $_.Reachable }.ComputerName
如果您有兴趣在枚举期间对可访问和不可访问的结果进行分组,可以使用 哈希表
,其中有2个 List<T>
值。
$result = @{
Online = [System.Collections.Generic.List[object]]::new()
Offline = [System.Collections.Generic.List[object]]::new()
}
Get-Content C:\servers.txt | ForEach-Object {
Test-Connection -ComputerName $_ -Count 1 -AsJob
} | Receive-Job -Wait -AutoRemoveJob | ForEach-Object {
$obj = [pscustomobject]@{
ComputerName = $_.Address
Reachable = $_.StatusCode -eq 0
}
if($obj.Reachable) {
return $result['Online'].Add($obj)
}
$result['Offline'].Add($obj)
}
$result.Online.ComputerName # => has all reachable records
英文:
<!-- language-all: sh -->
You can store the result of your jobs and then filter by Reachable
. I've also simplified your code a bit and added -AutoRemove
which I consider important to dispose your jobs when done.
$result = Get-Content C:\servers.txt | ForEach-Object {
Test-Connection -ComputerName $_ -Count 1 -AsJob
} | Receive-Job -Wait -AutoRemoveJob | ForEach-Object {
[pscustomobject]@{
ComputerName = $_.Address
Reachable = $_.StatusCode -eq 0
}
}
$online = $result | Where-Object Reachable
# if you want just the `ComputerName` values, you can do
$online = $result | Where-Object Reachable | ForEach-Object ComputerName
# or easier, using member-access enumeration and `.Where` method
$online = $result.Where{ $_.Reachable }.ComputerName
If you're interested in grouping the results between Reachable and Not Reachable during enumeration, the way to do it is with a hash table
having 2 List<T>
values.
$result = @{
Online = [System.Collections.Generic.List[object]]::new()
Offline = [System.Collections.Generic.List[object]]::new()
}
Get-Content C:\servers.txt | ForEach-Object {
Test-Connection -ComputerName $_ -Count 1 -AsJob
} | Receive-Job -Wait -AutoRemoveJob | ForEach-Object {
$obj = [pscustomobject]@{
ComputerName = $_.Address
Reachable = $_.StatusCode -eq 0
}
if($obj.Reachable) {
return $result['Online'].Add($obj)
}
$result['Offline'].Add($obj)
}
$result.Online.ComputerName # => has all reachable records
答案2
得分: 0
I believe the issue here is the pipe ft -autosize.
尝试将管道放在if/else语句之后,如下所示:
| ForEach-Object {
if ($_.Reachable -eq $true) {
$online += $_.ComputerName
}
}
然后,如果您想查看结果,您可以始终执行:
$online | ft -AutoSize
我还建议进行更好的格式化,因为一行中的所有内容不容易阅读。尝试像这样:
$online = @()
$pc = Get-Content C:\servers.txt
$pc | ForEach-Object {
Test-Connection -ComputerName $_ -Count 1 -AsJob
} | Get-Job | Receive-Job -Wait |
Select-Object @{Name='ComputerName';Expression={$_.Address}},@{Name='Reachable';Expression={
if ($_.StatusCode -eq 0) {
$true
} else {
$false
}
}} | ForEach-Object {
if ($_.Reachable -eq $true) {
$online += $_.ComputerName
}
}
$online | ft -AutoSize
英文:
I believe the issue here is the pipe ft -autosize.
Try to pipe after the if/else statement as per below:
| ForEach-Object {
if ($_.Reachable -eq $true) {
$online += $_.ComputerName
}
}
Then if you want to view the results you can always do:
$online | ft -AutoSize
I'd also suggest a better formatting as all one line isn't easy to read. Try something like this:
$online = @()
$pc = Get-Content C:\servers.txt
$pc | ForEach-Object {
Test-Connection -ComputerName $_ -Count 1 -AsJob
} | Get-Job | Receive-Job -Wait |
Select-Object @{Name='ComputerName';Expression={$_.Address}},@{Name='Reachable';Expression={
if ($_.StatusCode -eq 0) {
$true
} else {
$false
}
}} | ForEach-Object {
if ($_.Reachable -eq $true) {
$online += $_.ComputerName
}
}
$online | ft -AutoSize
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论