3 административных скрипта

    Нужно оживить паблик, поэтому немного административных скриптов.

    1. Получить сетевые настройки и конфиги доменных компов
    2. Поменять шлюз по умолчанию на доменных компах
    3. Получить статистику по почтовым ящикам

    1. Получить сетевые настройки и конфиги доменных компов.


    Обходит доменные компьютеры и собирает с них информацию. На выходе выбрасывается полноценный объект. Компьютер должен быть включен конечно же. Сценарий содержит пример работы через WMI. Запускать с домена.

    # запрашиваем кредиталы доменного админа
    $cred = Get-Credential
    <anchor>habracut</anchor>
    $Clients = Get-ADComputer -Filter * | Sort-Object name | Select-Object name
    $CompData = @()
    
    foreach ($cli in $Clients)    {
        if (( Test-Connection $cli.Name -Count 2 -Quiet ) -eq 'True')       {
            if ($cli.name -ne $env:COMPUTERNAME)        {
                #получаем информацию по WMI
                $os = Get-WmiObject -ComputerName $cli.name Win32_OperatingSystem -Credential $cred
                $net = Get-WmiObject -Class Win32_NetWorkAdapterConfiguration -Filter IPEnabled=TRUE -ComputerName $cli.name  -Credential $cred
                $nic = Get-WmiObject -Class Win32_NetWorkAdapter -ComputerName $cli.name  -Credential $cred | where {$_.adaptertype -eq 'Ethernet 802.3'} | where { $_.NetEnabled -eq 'True'}
                $disk = Get-WmiObject -Class Win32_DiskDrive -ComputerName $cli.name -Credential $cred 
    
                $props = [ordered]@{ Name=$os.CSName
                            OSName=$os.Caption
                            OSSN=$os.SerialNumber
                            OSVersion=$os.Version
                            OSSystemDirectory=$os.SystemDirectory
                            OSBuild=$os.BuildNumber
                            OSMUI=$os.MUILanguages
                            OSBootDevice=$os.BootDevice
                            NICNetConnectionID=$nic.NetConnectionID
                            NICName=$nic.Name
                            NICDeviceID=$nic.DeviceID
                            NICAdapterType=$nic.AdapterType
                            NICIndex=$nic.Index
                            NICInterfaceIndex=$nic.InterfaceIndex
                            NICMAC=$nic.MACAddress
                            NICManufacturer=$nic.Manufacturer
                            NICNetEnabled=$nic.NetEnabled
                            NICPhysical=$nic.PhysicalAdapter
                            NICProductName=$nic.ProductName
                            NICServiceName=$nic.ServiceName
                            NICSpeed=$nic.Speed
                            NetDHCPEnabled=$net.DHCPEnabled
                            NetIPAddress=$net.IPAddress
                            NetDefaultGateway=$net.DefaultIPGateway
                            DiskName=$disk.Caption 
                            DiskStatus=$disk.Status 
                            DiskDeviceId=$disk.deviceid 
                            DiskSerialNumber=$disk.serialnumber 
                            DiskSize=$disk.size 
                            }
    
                $obj = New-Object -TypeName PSObject -Property $props
                $CompData += $obj
            }
        }
    }
    
    $CompData
    

    2. Поменять шлюз по умолчанию


    Модифицируем предыдущий скрипт так чтобы он менял шлюз по умолчанию. (обязательно все проверяйте в своей среде перед запуском на живой системе!) Использует в для смены шлюза вызовы WMI т.к. через повершелл нужно удалить и снова создать адаптер, что приведет к потери связи с компьютером. Проверялся на Powershell 4 и 3, win 2012 и 8.

    $cred = Get-Credential
    
    $OldGateway = '192.168.30.1'
    $NewGateway = '192.168.30.50'
    
    $Clients = Get-ADComputer -Filter * | Sort-Object name | Select-Object name
    $CompData = @()
    
    foreach ($cli in $Clients)
    {
        if (( Test-Connection $cli.Name -Count 2 -Quiet ) -eq 'True')
        {
            if ($cli.name -ne $env:COMPUTERNAME)
            {
                $os = Get-WmiObject -ComputerName $cli.name Win32_OperatingSystem -Credential $cred
                $net = Get-WmiObject -Class Win32_NetWorkAdapterConfiguration -Filter IPEnabled=TRUE -ComputerName $cli.name  -Credential $cred
                $nic = Get-WmiObject -Class Win32_NetWorkAdapter -ComputerName $cli.name  -Credential $cred | where {$_.adaptertype -eq 'Ethernet 802.3'} | where { $_.NetEnabled -eq 'True'}
                $disk = Get-WmiObject -Class Win32_DiskDrive -ComputerName $cli.name -Credential $cred 
    
                $props = [ordered]@{ Name=$os.CSName
                            OSName=$os.Caption
                            OSSN=$os.SerialNumber
                            OSVersion=$os.Version
                            OSSystemDirectory=$os.SystemDirectory
                            OSBuild=$os.BuildNumber
                            OSMUI=$os.MUILanguages
                            OSBootDevice=$os.BootDevice
                            NICNetConnectionID=$nic.NetConnectionID
                            NICName=$nic.Name
                            NICDeviceID=$nic.DeviceID
                            NICAdapterType=$nic.AdapterType
                            NICIndex=$nic.Index
                            NICInterfaceIndex=$nic.InterfaceIndex
                            NICMAC=$nic.MACAddress
                            NICManufacturer=$nic.Manufacturer
                            NICNetEnabled=$nic.NetEnabled
                            NICPhysical=$nic.PhysicalAdapter
                            NICProductName=$nic.ProductName
                            NICServiceName=$nic.ServiceName
                            NICSpeed=$nic.Speed
                            NetDHCPEnabled=$net.DHCPEnabled
                            NetIPAddress=$net.IPAddress
                            NetDefaultGateway=$net.DefaultIPGateway
                            DiskName=$disk.Caption 
                            DiskStatus=$disk.Status 
                            DiskDeviceId=$disk.deviceid 
                            DiskSerialNumber=$disk.serialnumber 
                            DiskSize=$disk.size 
                            }
    
                $obj = New-Object -TypeName PSObject -Property $props
    
                $CompData += $obj
            }
        }
    }
    
    #$CompData
    ################################################################
    
    # Меняем шлюз
    foreach($Co in $CompData) {
             if ($Co.NetDefaultGateway = $OldGateway)       {
                $Co.Name
                $Co.netdefaultgateway
    
                $NWCards = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $co.Name -Credential $cred | where{ $_.ipenabled -eq $true }
                foreach ($nwc in $NWCards)       {
                    $gateway = $nwc.defaultipgateway
                    if ($gateway -eq $OldGateway)       {
                        $nwc.setgateways($NewGateway)
                    }
                }
             }
    }
    

    3. Получить статистику по почтовым ящикам


    Собирает статистику топ ящиков по размеру, топ ящиков по количеству писем, топ ящиков по удаленым айтемам (purge корзины 2 еще не произошел, только удаление писем пользователем), после формирует «красивый» отчет в HTML и отправляет на почту и складывает в папочку. Использовался как ежемесячный репортер состояния базы, устанавливался в таск шедалер. Запускать на сервере exchange. Проверялось на Exchange 2010.

    <# 
        по умолчанию выбирает по 25 топ мэйлбоксов
        сохрание отчета на диск отключено
    #>
    
    Param (  [int]$TopCount = 25,
            [boolean]$SaveReport = $false,
            [string]$ReportPath = 'C:\Reports\MailboxReport.html',
            [boolean]$SendReport = $true,
            [string]$ReportMail1 = 'admin@mail.local'
        )
    
    # check snapin present
    $EX2010 = $false
    
    $snaps = Get-PSSnapin
    foreach( $snap in $snaps )  {
        if ($snap.Name -eq 'Microsoft.Exchange.Management.PowerShell.E2010')   {
            $EX2010 = $true
        }
    }
    
    if ($EX2010 -eq $false) {
        Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
    }
    
    $boxes = Get-Mailbox | Get-MailboxStatistics | sort TotalItemSize -Descending
    $TotalSize = $boxes | sort TotalItemSize -Descending | select -First $TopCount
    
    # самые толстые ящики
    $Size = @()
    foreach ($box in $TotalSize)  {
        $propsTotalSize = [ordered]@{   DisplayName=$box.DisplayName
                                        User=$box.LastLoggedOnUserAccount
                                        Database=$box.Database
                                        TotalSize=$box.TotalItemSize
                                        ItemCount=$box.ItemCount
                                        DeletedItemCount=$box.DeletedItemCount
                                        TotalDeletedSize=$box.TotalDeletedItemSize
                            }
                $obj = New-Object -TypeName PSObject -Property $propsTotalSize
                $Size += $obj
    }
    
    # топ удаленых без purge
    $Deleted = $boxes | sort TotalDeletedItemSize -Descending | select -First $TopCount
    $Del = @()
    foreach ($box in $Deleted)   {
        $propsDeleted = [ordered]@{   DisplayName=$box.DisplayName
                                      User=$box.LastLoggedOnUserAccount
                                      Database=$box.Database
                                      TotalSize=$box.TotalItemSize
                                      ItemCount=$box.ItemCount
                                      DeletedItemCount=$box.DeletedItemCount
                                      TotalDeletedSize=$box.TotalDeletedItemSize
                            }
                $obj = New-Object -TypeName PSObject -Property $propsDeleted
                $Del += $obj
    }
    
    # топ по количеству писем, слишком много индикатор что пользователь сваливает все в кучу и нуждается в автоматических правилах
    $Top = $boxes | sort ItemCount -Descending | select -First $TopCount
    $TopItems = @()
    foreach ($box in $Top)  {
        $propsTopItems = [ordered]@{   DisplayName=$box.DisplayName
                                       User=$box.LastLoggedOnUserAccount
                                       Database=$box.Database
                                       TotalSize=$box.TotalItemSize
                                       ItemCount=$box.ItemCount
                                       DeletedItemCount=$box.DeletedItemCount
                                       TotalDeletedSize=$box.TotalDeletedItemSize
                            }
                $obj = New-Object -TypeName PSObject -Property $propsTopItems
                $TopItems += $obj
    }
    
    ##### HTML generating
    Write-Verbose 'HTML fragment producing'
    $fragTopItems = $TopItems | ConvertTo-Html -As table -Fragment -PreContent '<h2>Топ ящиков по количеству писем (items count)</h2>' | Out-String
    $fragTopSizes =     $Size | ConvertTo-Html -As table -Fragment -PreContent '<h2>Топ ящиков по размеру</h2>' | Out-String
    $fragTopDelItems =   $Del | ConvertTo-Html -As table -Fragment -PreContent '<h2>Топ ящиков по удаленным письмам (purge еще не было)</h2>' | Out-String
    
    Write-Verbose 'definiting CSS'
    $head = @'
    <style>
    body { background-color:#ffffff; font-family:Tahoma; font-size:12pt; }
    td, th { border:1px solid black; border-collapse:collapse; }
    th { color:white; background-color:black; }
    table, tr, td, th { padding: 2px; margin: 0px }
    table { font-family: "Lucida Sans Unicode", "Lucida Grande", Sans-Serif; font-size: 14px;
    border-radius: 10px; border-spacing: 0; text-align: center; }
    th { background: #BCEBDD; color: white; text-shadow: 0 1px 1px #2D2020; padding: 10px 20px; }
    th, td { border-style: solid; border-width: 0 1px 1px 0; border-color: white; }
    th:first-child, td:first-child { text-align: left; }
    th:first-child { border-top-left-radius: 10px; }
    th:last-child { border-top-right-radius: 10px; border-right: none; }
    td { padding: 10px 20px; background: #F8E391; }
    tr:last-child td:first-child { border-radius: 0 0 0 10px; }
    tr:last-child td:last-child { border-radius: 0 0 10px 0; }
    tr td:last-child { border-right: none; }
    </style>
    '@
    
    Write-Verbose 'HTML producing'
    $Date = Get-Date
    
    if ($SaveReport = $true) {
        $rep = ConvertTo-HTML -head $head -PostContent $fragTopSizes, $fragTopDelItems, $fragTopItems -PreContent "<h1>Отчет по почтовым ящикам $Date</h1>" | Out-String
        $rep | Out-File $ReportPath
    }
    
    # Sending Email to admins
    if ($SendReport = $true) {
        $encoding = [System.Text.Encoding]::UTF8
        $body = ConvertTo-HTML -head $head -PostContent $fragTopSizes, $fragTopDelItems, $fragTopItems -PreContent "<h1>Отчет по почтовым ящикам $Date</h1>" | Out-String
    
        Write-Verbose "Sending e-mail"
        $params = @{'To'=$ReportMail1
                   'From'='bot@geomex.local'
                   'Subject'="Mailbox report $Date"
                   'Body'=$Body
                   'BodyAsHTML'=$True
                   'SMTPServer'='mail.domain.local'}
        Send-MailMessage @params -Encoding $encoding
    }
    

    Всех с майскими праздниками.
    Метки:
    Поделиться публикацией
    Похожие публикации
    Комментарии 9
    • +3
      Более-менее полезно выглядит только по почтовым ящикам. Остальное — практически неработоспособное решение. Мало того, что «запускать с домена» (что это? с КД запускать чтоли??), так и куча недоработок, которые суммарно не позволят это использовать. Про смену шлюза через доменный скрипт вовсе промолчу — неужто хочется в случае ошибок бегать и менять настройки на сотнях-тысячах компах?
      Подробнее могу про первый подсказать:
      1. Нет смысла собирать информацию с компьютеров, без сброса её в какую-либо базу, или хотя бы текстовый файл. Компьютер может быть выключен, и информации по нему не будет. Поэтому, правильнее сделать список ПК в файле, и периодически прогонять скрипт, пополняя файл данными (ну или базу, если есть).
      2. Нет никакой обработки ошибок. У меня используется подобный скрипт, правда запускаю на своём ПК (учётка имеет адм.права на всех ПК из списка). Так вот, при более чем 3-летней эксплуатации и постоянного «допиливания» выяснилось, что компьютер может быть выключен (нужно периодически опрашивать и дозаписывать отсутствующие данные в файл или базу), на компьютере может не работать WMI (это серьёзные проблемы, и нужно решать, для этого ошибки отлавливать и записывать в лог), на компьютере может даже не работать RPC (при доступности по пингу), и до компьютера могут быть перекрыты какие-либо порты на сетевом оборудовании. Да и много других может быть ошибок, и в некоторых случаях они будут критическими, и скрипт не отработает как надо или запишет в базу мусор. Поэтому используем $ErrorActionPreference, trap и в нужных случаях меняем поведение при обработке.
      3. Мелочь, но: ненужные данные зачем собирать? К примеру, объект $disk будет содержать и всякие картридеры, встроенную память на принтерах, подключенные флешки и прочее. Как минимум можно сделать что-то типа if ($disk.mediatype.Contains(«Fixed») -and ($disk.Size -gt 0)). К тому же объект $disk может оказаться массивом (дисков несколько), и DiskName=$disk.Caption даст ошибку, их нужно всегда перебирать в цикле foreach. (это же и процессоров касается). Да и вместо caption диска лучше взять model (если нужны всё-таки fixed диски).

      Но в качестве заготовки скрипты конечно пойдут, каждый допилит под себя.
      • 0
        обычно перед использованием таких штук надо подумать

        вы кстати как WMI включаете через политики?
        • +2
          1. Лучше в логон скрипты запихать и логировать в тот же файл.
          2. Тоже самое.
          3. три команды выпелено в большущий скрипт. В Гет-маилбоксес добавте анлимитед.

          В сотый миллиардный раз одно и тоже, ScriptCenter вам в помощь, там уже по 10 раз в любых вариациях все
          написано.
          • +1
            Тут уже высказались выше по поводу всего этого.
            Я хочу спросить по поводу шлюза — чем же вам так не понравился DHCP?
            • 0
              ну надо было, такая задача была. адреса на некоторых машинах были статические
              • 0
                Ну так как-бы если на некоторых то это решается привязкой mac-ip
            • 0
              Больше 12 лет использую WMI как средство администрирования по части сбора и анализа различной статистики с кучи серверов. Был случай, когда экстренно с полуторатысячи клиентских мест он помог собрать нужные сведения.

              Но, надо сказать, никогда не решался скриптом разом и без логгирования править настройки на куче мест. Лень-то она конечно двигатель прогресса, но не все же мы самураи. Преклоняюсь перед «смелостью» автора.
              • 0
                если кто запустит просто так этот скрипт будет конечно атомно ))) поменяется шлюз на ВСЕХ машинах кроме контроллера )))
                ну я думаю что кто на это пойдет настроит фильтр на get-adcomputers
                • 0
                  Скриптам и программам доверяю больше, чем людям, себе же — из всех людей — меньше всего. Потому как себе любимому больше всего позволяю. И поэтому, допустить выполнение действия, которому не придумал отката — не реализую. Иногда бывает помутнение рассудка и можешь просто перепутать. Все мы люди. Хотя все это специфично ;) Если сбить пароль, или настройки кроме сетевых — можно еще раз запустить скрипт и внести изменения обратно. А вот с сетевыми настройками — тут как гильотниа — голова отлетает и обратно ее не пришьешь, если только ножками все не оббежать.

              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.