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)
pak-nikolai
04.05.2017 09:40обычно перед использованием таких штук надо подумать
вы кстати как WMI включаете через политики?
brainfair
04.05.2017 09:49+21. Лучше в логон скрипты запихать и логировать в тот же файл.
2. Тоже самое.
3. три команды выпелено в большущий скрипт. В Гет-маилбоксес добавте анлимитед.
В сотый миллиардный раз одно и тоже, ScriptCenter вам в помощь, там уже по 10 раз в любых вариациях все
написано.
iborzenkov
04.05.2017 11:49+1Тут уже высказались выше по поводу всего этого.
Я хочу спросить по поводу шлюза — чем же вам так не понравился DHCP?pak-nikolai
04.05.2017 12:21ну надо было, такая задача была. адреса на некоторых машинах были статические
helgisbox
04.05.2017 13:29Больше 12 лет использую WMI как средство администрирования по части сбора и анализа различной статистики с кучи серверов. Был случай, когда экстренно с полуторатысячи клиентских мест он помог собрать нужные сведения.
Но, надо сказать, никогда не решался скриптом разом и без логгирования править настройки на куче мест. Лень-то она конечно двигатель прогресса, но не все же мы самураи. Преклоняюсь перед «смелостью» автора.pak-nikolai
04.05.2017 13:30если кто запустит просто так этот скрипт будет конечно атомно ))) поменяется шлюз на ВСЕХ машинах кроме контроллера )))
ну я думаю что кто на это пойдет настроит фильтр на get-adcomputershelgisbox
04.05.2017 13:44Скриптам и программам доверяю больше, чем людям, себе же — из всех людей — меньше всего. Потому как себе любимому больше всего позволяю. И поэтому, допустить выполнение действия, которому не придумал отката — не реализую. Иногда бывает помутнение рассудка и можешь просто перепутать. Все мы люди. Хотя все это специфично ;) Если сбить пароль, или настройки кроме сетевых — можно еще раз запустить скрипт и внести изменения обратно. А вот с сетевыми настройками — тут как гильотниа — голова отлетает и обратно ее не пришьешь, если только ножками все не оббежать.
AVX
Более-менее полезно выглядит только по почтовым ящикам. Остальное — практически неработоспособное решение. Мало того, что «запускать с домена» (что это? с КД запускать чтоли??), так и куча недоработок, которые суммарно не позволят это использовать. Про смену шлюза через доменный скрипт вовсе промолчу — неужто хочется в случае ошибок бегать и менять настройки на сотнях-тысячах компах?
Подробнее могу про первый подсказать:
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 диски).
Но в качестве заготовки скрипты конечно пойдут, каждый допилит под себя.