Многопоточный сканер сети

Натолкнулся в форумах на просьбу написать сканер сети работающий в несколько потоков, но на скриптах Smile Задачка показалась мне интересной и даже полезной, поэтому родился вот такой скриптик:

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, но я надеюсь все мои читатели уже до него обновились Smile

Опубликовано в 2.0, PowerShell, Scripting. Метки: , , . 6 комментариев »

Выкачивание драйверов с сайта HP

usbVacuum Не так давно мне понадобилось скачать драйверы и утилиты для множества моделей компьютеров HP. Учитывая что обычно для каждой модели приводится несколько десятков драйверов, скачивать их вручную и раскладывать по папкам мне показалось слишком долго и нудно. Кроме того я не хотел устанавливать какие либо менеджеры закачек которые помогли бы просто выдрать все ссылки со страницы, да они и не смогли бы правильно разложить файлы по категориям… Поэтому я решил написать простенький сценарий, который бы разбирал html страницы с драйверами для модели, понимал бы к какой категории относится драйвер или утилита, скачивал бы их, и раскладывал бы в соответствующие папки (при необходимости создавая эти папки самостоятельно).

Читать далее…

Выдираем ссылки из вебстранички

Для большинства случаев использования регулярных выражений в PowerShell применяются операторы -match, -replace, и командлет Select-String. Но иногда их возможностей недостаточно, и тогда на помощь приходит класс [regex] принося всю мощь регулярных выражений .Net 🙂 Одно из самых простых его применений — выборка из куска текста нескольких вхождений одного выражения. Для примера — достанем ссылки из кода вебстраницы. Сразу замечу что выражение определяющее url не точное, но в большинстве случаев его будет более чем достаточно.
Итак, для начала объявим функцию для загрузки кода веб-страницы (это обновлённая версия Get-WWWString):

function Get-WwwString ([string]$Url, [string]$Encoding="windows-1251", [System.Management.Automation.PSCredential]$ProxyCredential = $GlobalCreds)            
{            
        $wc = new-object System.Net.WebClient            
        $wc.Encoding = [System.Text.Encoding]::GetEncoding($Encoding)            
        $wc.UseDefaultCredentials = $true            
        if ($ProxyCredential) {$wc.Proxy.Credentials = $ProxyCredential.GetNetworkCredential()}            
        $wc.DownloadString($url)            
}

Теперь загружаем страницу, и вытаскиваем ссылки…

$Text = Get-WwwString "http://ya.ru"            
            
[regex]$reg = '"(\w+://[^"]+)"'            
$match = $reg.match($Text)            
while ($match.Success)            
{            
    $match.Groups[1].value            
    $match = $match.nextMatch()            
}
Опубликовано в 2.0, Learn, PowerShell, Scripting. Метки: . Комментарии к записи Выдираем ссылки из вебстранички отключены

Windows Management Framework released!

Около часа назад наконец произошло то чего все долго ждали 🙂 Вышел в релиз Windows Management Framework! Это комплект в который входят следующие компоненты:

  • WinRM 2.0
  • Windows PowerShell 2.0
  • BITS 4.0

Он выпущен для следующих операционных систем:

  • Windows XP
  • Windows Server 2003
  • Windows Vista
  • Windows Server 2008

Да, да, релиз PowerShell v2 наконец то наступил для всех (ранее он был доступен лишь в составе Windows 7 и Windows Server 2008 R2)

Скачать можно тут — http://support.microsoft.com/kb/968929.

Опубликовано в 2.0, News, PowerShell, Scripting, Vista, Windows 2008. Метки: , , , , . 2 комментария »

Windows 7 Resource Kit PowerShell Pack

James Brundage, один из разработчиков PowerShell, выложил коллекцию модулей PowerShell написанных для Windows 7 Resource Kit. Один из них, IsePack, я уже давно активно использовал, и ждал когда же он наконец появится в публичном доступе 🙂 Этот модуль расширяет возможности PowerShell ISE, добавляя своё меню с различными интересными плюшками 🙂
isepack
Большая часть кода с подсветкой в моих последних постах вставлена именно с его помощью 🙂
Впрочем это только один модуль из тех что выложил Джеймс. Весь PowerPack можно скачать здесь. Ниже полный список модулей:

WPK — Легко и быстро создаёт пользовательские интерфейсы из PowerShell. Типа HTA, но просто 🙂 Более 600 скриптов для быстрого создания интерфейсов. Для начала рекомендуется прочитать Writing User Interfaces with WPK

IsePack — Расширяет ISE, добавляя более 35 действий.

TaskScheduler — Выводит назначенные задания, создаёт и удаляет их.

FileSystem — Отслеживание файлов и папок, проверка на дубликаты и свободного места на диске.

DotNet — Explore loaded types, find commands that can work with a type, and explore how you can use PowerShell, DotNet and COM together Исследуйте загруженные типы, находите команды для работы с ними, и изучайте как вы можете использовать PowerShell, DotNet и COM вместе.

PSImageTools
Инструменты для конвертирования, поворота, изменения размера, обрезки изображений и получения их метаданных.

PSRSS — Работа с FeedStore из PowerShell .

PSSystemTools — Получение информации об операционной системе и оборудовании.

PSUserTools — Получение списка пользователей, проверка привилегий и т.п.

PSCodeGen — Генерирует PowerShell скрипты, код C# и P/Invoke.

Я пока еще не пробовал все эти модули, так что неточности в переводе обязательны 🙂 Качаем и смотрим 🙂

Опубликовано в 2.0, PowerShell, Scripting, Utility, Windows 7. Метки: , , , , , , . Комментарии к записи Windows 7 Resource Kit PowerShell Pack отключены

Включаем PowerShell Remoting через групповые политики.

Windows 7 и Windows Server 2008 R2 уже в состоянии RTM, а в них уже встроен PowerShell v2.0. Соответственно, самые прогрессивные администраторы уже смогут использовать PowerShell Remoting в реальном, не тестовом окружении.

Так как в целях безопасности Remoting разумеется отключён в конфигурации по умолчанию, то надо будет его включить. Сделать это можно с помощью командлета Enable-PSRemoting (причем надо выполнить его и на управляющем и управляемом компьютерах). Чтобы командлет не задавал лишних вопросов, достаточно добавить к нему ключ –Force.

Но как я уже сказал выше, время тестирования заканчивается, и скоро нам понадобится включать Remoting на множестве наших компьютеров. Enable-PSRemoting для этого уже мало подходит. Можно конечно включить его в сценарий загрузки компьютера, но это мягко говоря не эффективно.

И тут нам на помощь, приходят старые добрые групповые политики 🙂 К сожалению (или к счастью?) галочка “сделать чтоб ремотинг заработал” отсутствует 🙂 Так что с помощью групповой политики придётся произвести несколько отдельных настроек.

Во-первых надо создать “Listener”, так называемый “слушатель”, который будет принимать входящие подключения WinRM на определённый порт, с определёнными настройками. Listener’ов можно создать несколько, назначить различные разрешения на подключения к ним, порты, параметры безопасности, и ограничения. Но мы сейчас ограничимся созданием простого “слушателя” с настройками по умолчанию. Он будет принимать подключения от пользователей с административными полномочиями, на порт 5985. Создать его легко с помощью административных шаблонов групповой политики: Computer Configuration / Policies / Administrative Templates / Windows Components / Windows Remote Management (WinRM) / WinRM Service. Тут, в элементе Allow automatic configuration of listeners можно разрешить автоматическое создание “слушателя” по умолчанию, и указать для него диапазоны адресов с которых он будет принимать подключения (ipv4 и ipv6). Впрочем можно разрешить подключения отовсюду, поставив звёздочку (*). Рядом можно изменить некоторые другие настройки WinRM, или включить Listener’ы слушающие на портах 80 и 443 (Turn On Compatibility HTTP(S) Listener), стандартных для HTTP и HTTPS.

psr_listener

Ну и последняя настройка – разрешить подключения на соответствующий порт, в Windows Firewall. Делается это тоже с помощью групповых политик, в узле Computer Configuration / Policies / Windows Settings / Security Settings / Windows Firewall with Advanced Security / Inbound Rules.

Здесь просто нужно с помощью мастера, создать правило разрешающее подключение на соответствующие порты. Для этого можно использовать предустановленное правило Windows Remote Management.

psr_fw

Всё, теперь останется лишь подождать применения этой политики на компьютеры.

Ну и напоследок, файлы встроенной справки по Remoting’у:

PS C:\> get-help about_remote* | Format-Table Name, Synopsis -AutoSize

Name                         Synopsis
----                         --------
about_remote                 Describes how to run remote commands in Windows PowerShell.
about_remote_FAQ             Contains questions and answers about running remote commands
about_remote_jobs            Describes how to run background jobs on remote computers.
about_remote_output          Describes how to interpret and format the output of remote commands.
about_remote_requirements    Describes the system requirements and configuration requirements for
about_remote_troubleshooting Describes how to troubleshoot remote operations in Windows PowerShell.

Очень рекомендую с ними ознакомится.

#Requires –Version 2.0

Наверное у многих возникало желание делать в начале своего скрипта проверку например версии PowerShell. Ведь если вы используете новые возможности 2.0, а файл будет запущен под 1.0, то часть команд сработает, а другая нет, что в результате может привести как минимум к ошибкам, а как максимум – к большим проблемам.

Вообще написать проверку версии несложно. У PowerShell 2.0 есть специальная переменная, $PSVersionTable в которой содержится вся необходимая информация о версии:

[PS <1> C:\root] $psversiontable

Name                           Value
----                           -----
CLRVersion                     2.0.50727.4918
BuildVersion                   6.1.7100.0
PSVersion                      2.0
WSManStackVersion              2.0
PSCompatibleVersions           {1.0, 2.0}
SerializationVersion           1.1.0.1
PSRemotingProtocolVersion      2.0

Ну а версию 1.0 легко опознать по отсутствию этой переменной 🙂 В результате получаем такую функцию:

function Get-Version {if ($PSVersionTable){$PSversionTable.PSVersion.ToString()} else {"1.0"}}

Но на самом деле всё это – лишние движения. Всё можно сделать гораздо проще.

Если ваш скрипт требует версии 2.0, вам достаточно в его начале поместить следующую строку:

#Requires -Version 2.0

PowerShell поймёт эту директиву, и при попытке запуска сценария в оболочке с версией ниже указанной, выдаст ошибку:

PS C:\Temp> . C:\Temp\test.ps1
The script 'test.ps1' cannot be run because it contained a "#requires" statement at 
line 1 for Windows PowerShell version 2.0 which is incompatible with the installed 
Windows PowerShell version of 1.0.
At line:1 char:2
+ .  <<<< C:\Temp\test.ps1

Вполне понятно, и не сложно.

Ниже, полный список критериев которые позволяет указать деректива Requires:

#requires -shellid 
#requires -version 
#requires -pssnapin  [-version ]

Например чтобы разрешить запуск сценария лишь в оболочке с подгруженной оснасткой AD Cmdlets, достаточно сделать так:

#Requires -PSSnapin Quest.ActiveRoles.ADManagement

Можно даже указать конкретную версию оснастки добавив ключ –Version. Причем если вы это сделаете, скрипт будет выполнятся именно с этой версией. Даже если установлена более поздняя – будет выдана ошибка.

Опубликовано в 2.0, PowerShell. Метки: , , . 2 комментария »