Натолкнулся в форумах на просьбу написать сканер сети работающий в несколько потоков, но на скриптах Задачка показалась мне интересной и даже полезной, поэтому родился вот такой скриптик:
ThreadPing.ps1
Param ( [string[]]$Address = $(1..20 | %{"192.168.1.$_"}), [int]$Threads = 5 ) write-host "Distributing addresses around jobs" $JobAddresses = @{} $CurJob = 0 $CurAddress = 0 while ($CurAddress -lt $Address.count) { $JobAddresses[$CurJob] += @($Address[$CurAddress]) $CurAddress++ if ($CurJob -eq $Threads -1) { $CurJob = 0 } else { $CurJob++ } } $Jobs = @() foreach ($n in 0 .. ($Threads-1)) { Write-host "Starting job $n, for addresses $($JobAddresses[$n])" $Jobs += Start-Job -ArgumentList $JobAddresses[$n] -ScriptBlock { $ping = new-object System.Net.NetworkInformation.Ping Foreach ($Ip in $Args) { trap { new-object psobject -Property { Status = "Error: $_" Address = $Ip RoundtripTime = 0 } Continue } $ping.send($Ip,100) | select ` @{name="Status"; expression={$_.Status.ToString()}}, @{name = "Address"; expression={$Ip}}, RoundtripTime } } } write-host "Waiting for jobs" $ReceivedJobs = 0 while ($ReceivedJobs -le $Jobs.Count) { foreach ($CompletedJob in ($Jobs | where {$_.State -eq "Completed"})) { Receive-Job $CompletedJob | select status, address, roundtriptime $ReceivedJobs ++ sleep 1 } } Remove-Job $Jobs write-host "Done."
У скрипта два аргумента:
- Threads – число потоков
- Address – диапазон ip-адресов в виде массива строк. Например чтобы просканировать адреса с 192.168.1.1 по 192.168.1.254 можно использовать следующую конструкцию: 1..254 | ${"192.168.1.$_"}
Пример использования:
PS > .\ThreadPing.ps1 -Address (1..20|%{"192.168.1.$_"}) -threads 5 Distributing addresses around jobs Starting job 0, for addresses 192.168.1.1 192.168.1.6 192.168.1.11 192.168.1.16 Starting job 1, for addresses 192.168.1.2 192.168.1.7 192.168.1.12 192.168.1.17 Starting job 2, for addresses 192.168.1.3 192.168.1.8 192.168.1.13 192.168.1.18 Starting job 3, for addresses 192.168.1.4 192.168.1.9 192.168.1.14 192.168.1.19 Starting job 4, for addresses 192.168.1.5 192.168.1.10 192.168.1.15 192.168.1.20 Waiting for jobs Done. Status Address RoundtripTime ------ ------- ------------- TimedOut 192.168.1.2 0 TimedOut 192.168.1.7 0 Success 192.168.1.12 1 TimedOut 192.168.1.17 0 Success 192.168.1.1 0 Success 192.168.1.6 1 TimedOut 192.168.1.11 0 TimedOut 192.168.1.16 0 Success 192.168.1.3 10 TimedOut 192.168.1.8 0 TimedOut 192.168.1.13 0 TimedOut 192.168.1.18 0 TimedOut 192.168.1.4 0 TimedOut 192.168.1.9 0 TimedOut 192.168.1.14 0 TimedOut 192.168.1.19 0 TimedOut 192.168.1.5 0 TimedOut 192.168.1.10 0 TimedOut 192.168.1.15 0 TimedOut 192.168.1.20 0
Так как вывод полностью объектный, в лучших традициях PowerShell’а, то результатами легко оперировать. Например, чтобы получить лишь отзывающиеся на пинг хосты, можно использовать where:
.\ThreadPing.ps1 -Address (1..254|%{"192.168.1.$_"}) -threads 20 | where {$_.status -eq "success"}
A что бы выбрать лишь адреса, достаточно добавить Select –ExpandProperty
$IPs = 1..3 | %{$s=$_; 1..254 | %{"192.168.$s.$_"}} .\ThreadPing.ps1 -Address $Ips -threads 20 | where {$_.status -eq "success"} | Select -expandproperty Address
Да, кстати, сценарий использует фоновые работы, поэтому будет работать только в PowerShell 2.0, но я надеюсь все мои читатели уже до него обновились