Можно ли как-нибудь использовать этот фрагмент кода с Test-NetConnection -ComputerName $_ -Port 5985
вместо Test-Connection -ComputerName $_ -Count 1 -AsJob
? Я не могу использовать -AsJob
с командлетом Test-NetConnection
. Есть ли обходные пути?
Вот мой код:
$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
В server.txt просто есть имена хостов всех машин в сети.
5.1.19041.2673. 5. Мы не можем обновить все PowerShell в среде. ключ здесь в том, что online
будет содержать все работающие серверы, чтобы я мог одновременно взаимодействовать с этими системами. Вот почему работа имеет ключевое значение.
А установка модулей? Это также может быть легко с помощью Start-ThreadJob
, и вы можете установить его с помощью Install-Module ThreadJob -Scope CurrentUser
Было бы лучше придерживаться значений по умолчанию, если это возможно.
С ванильной Windows PowerShell 5.1 лучшее, что вы можете получить, — это использовать RunspacePool , за кодом непросто следить, и по уважительной причине в PowerShell доступно множество модулей для обработки многопоточности. Наиболее рекомендуемым будет ThreadJob.
Этот ответ предлагает «копируемую» версию функции, которая может обрабатывать многопоточность из конвейера, аналогичную ForEach-Object -Parallel
, но совместимую с Windows PowerShell 5.1.
$ProgressPreference = 'Ignore'
$maxThreads = 32 # How many jobs can run at the same time?
$pool = [runspacefactory]::CreateRunspacePool(1, $maxThreads,
[initialsessionstate]::CreateDefault2(), $Host)
$pool.Open()
$jobs = [System.Collections.Generic.List[hashtable]]::new()
Get-Content C:\servers.txt | ForEach-Object {
$instance = [powershell]::Create().AddScript({
param($computer)
[pscustomobject]@{
Computer = $computer
Port = 5985
PortOpen = Test-NetConnection $computer -Port 5985 -InformationLevel Quiet
}
}).AddParameters(@{ computer = $_ })
$instance.RunspacePool = $pool
$jobs.Add(@{
Instance = $instance
Async = $instance.BeginInvoke()
})
}
$result = while($jobs) {
$job = $jobs[[System.Threading.WaitHandle]::WaitAny($jobs.Async.AsyncWaitHandle)]
$job.Instance.EndInvoke($job.Async)
$job.Instance.Dispose()
$null = $jobs.Remove($job)
}
$pool.Dispose()
$result | Where-Object PortOpen # filter only for computers with this port open
Означает ли это, что он может запускать это максимум на 32 системах одновременно? Также есть ли способ, как в моем предыдущем вопросе, просто собрать все системы с именем хоста в массив online
?
@unixpipe это число может быть изменено на столько, сколько вы хотите, или на столько, сколько ваш компьютер может обработать, а что касается хостов в сети, я полагаю, что уже предоставил это в ответе $result | Where-Object PortOpen
вам просто нужно расширить свойство Computer
оттуда, чтобы получить массив значений
Спасибо. Я смог это получить. Проблема в том, что я могу не знать, сколько систем на самом деле работает. Может быть 4000 или даже 5000. Мне просто установить максимальное значение 5000 или это просто невозможно с помощью этого метода?
@unixpipe нет, $maxThreads = 32
никак не влияет на результаты. Эта переменная предназначена для того, чтобы сообщить пулу пространства выполнения, сколько потоков может выполняться одновременно, и больше ничего. 32
— приличное число, если вы поднимете его слишком сильно, вы можете сломать сеанс PowerShell. я бы оставил с этим значением
У @unixpipe была опечатка, моя ошибка, смотрите обновление (отсутствует $instance.RunspacePool = $pool
)
Я собирался принять ответ только сейчас, потому что он работал еще до того, как вы упомянули отсутствующий оператор, но не могли бы вы уточнить, почему он работал без него и будет ли он работать без него?
@unixpipe это работает, потому что пул пространства выполнения не является обязательным для запуска кода в отдельном потоке, все, что вам нужно, это экземпляр powershell ([powershell]::Create()....
), но без пула все экземпляры будут работать одновременно. Пул — это механизм управления потоками, он сообщает потокам, когда они могут «начать работу».
Какую версию PowerShell вы используете? Это может быть довольно легко с
ForEach-Object -Parallel
если работает PowerShell 7+, в противном случае эта функция может помочь github.com/santisq/PS-NetScanners/blob/main/…