learning:ps
Различия
Показаны различия между двумя версиями страницы.
Предыдущая версия справа и слеваПредыдущая версияСледующая версия | Предыдущая версия | ||
learning:ps [31.05.2019 13:28] – [090 СИНОНИМЫ ДЛЯ ПАРАМЕТРОВ] viacheslav | learning:ps [12.02.2025 09:59] (текущий) – [Регулярные выражения (regex) для разбора текстовых файлов] viacheslav | ||
---|---|---|---|
Строка 1: | Строка 1: | ||
+ | ===== Курс в " | ||
+ | <code powershell> | ||
+ | get-service | get-member | ||
+ | # или | ||
+ | get-service | gm | ||
+ | </ | ||
+ | |||
+ | ==== 7. Форматирование результатов ==== | ||
+ | <code powershell> | ||
+ | get-command -verb format -module *util* | ||
+ | |||
+ | dir c:\windows | ft BaseName, | ||
+ | |||
+ | # Выравнивание по правому краю: | ||
+ | Get-Service | ft @{n=" | ||
+ | |||
+ | # Список: | ||
+ | Get-Service | fl Name,Status | ||
+ | |||
+ | # Широкий - несколько колонок: | ||
+ | Get-Service | sort status | format-wide Name -Column 4 -GroupBy status | ||
+ | </ | ||
+ | |||
+ | ==== 8. Начало и конец конвейера ==== | ||
+ | Конец - обычно выгрузка куда-то, | ||
+ | <code powershell> | ||
+ | Get-Command -Verb Export, | ||
+ | ConvertTo-Csv | ||
+ | ConvertTo-Html | ||
+ | ConvertTo-Json | ||
+ | ConvertTo-Xml | ||
+ | Export-Alias | ||
+ | Export-Clixml | ||
+ | Export-Csv | ||
+ | Export-FormatData | ||
+ | Export-PSSession | ||
+ | |||
+ | # Результаты в окошке с фильтрами | ||
+ | get-service | Out-Gridview | ||
+ | |||
+ | Get-Service | ConvertTo-Html -Title " | ||
+ | </ | ||
+ | ==== 9. Привязка параметров в конвейере ==== | ||
+ | <code powershell> | ||
+ | Одно и то же: | ||
+ | dir c:\windows | format-wide | ||
+ | Format-Wide -InputObject (dir c:\windows) | ||
+ | </ | ||
+ | Круглые скобки нужны для добавления результатов другого конвейера команде, | ||
+ | |||
+ | ==== 10. Переменные ==== | ||
+ | Жизненный цикл переменной: | ||
+ | <code powershell> | ||
+ | get-command -noun variable | ||
+ | |||
+ | # Есть диск с именем Variable: | ||
+ | Get-PSDrive | ||
+ | # список переменных | ||
+ | dir variable: | ||
+ | </ | ||
+ | |||
+ | Свойства вызываются через точку, методы - добавляются скобки | ||
+ | <code powershell> | ||
+ | $test1.length | ||
+ | $test1.gettype() | ||
+ | $test1.Substring(2, | ||
+ | </ | ||
+ | |||
+ | <code powershell> | ||
+ | # Менять тип переменной можно на ходу, но можно задать тип жёстко: | ||
+ | [int]$test5 = 100 | ||
+ | # можно записать туда дробное число, | ||
+ | $test5 = 100.25 | ||
+ | # но значение всё равно будет целочисленным, | ||
+ | # Строку и т. п. записать туда не получится. | ||
+ | </ | ||
+ | |||
+ | Вывести количество символов имени самого большого файла в c:\Windows | ||
+ | <code powershell> | ||
+ | $test1 = dir c:\windows |sort Length -Descending | select -ExpandProperty Name -First 1 | ||
+ | $test1.length | ||
+ | |||
+ | # Массив переменных | ||
+ | $test1 = 10, 20, 30, 40, 50 | ||
+ | |||
+ | # Нумерация - с нуля: | ||
+ | $test1[2] # | ||
+ | $test1.count # | ||
+ | $test1[$test1.count - 1] # последний элемент массива | ||
+ | $test1.gettype() # тип данных - массив (array) | ||
+ | </ | ||
+ | Если в массиве изменить какие-то данные на другой тип, то тип данных всего массива превратится в строку (в 5-й версии powershell - нет). | ||
+ | <code powershell> | ||
+ | $test1[2] = " | ||
+ | |||
+ | $s = get-service | ||
+ | $s[5].status.tostring().length | ||
+ | </ | ||
+ | |||
+ | ==== 11. Программные конструкции ==== | ||
+ | Цикл.\\ | ||
+ | С предусловием - выполнять цикл, пока условие верно: | ||
+ | <code powershell> | ||
+ | $i=8 | ||
+ | while ($i -gt 0) | ||
+ | { | ||
+ | $i; # Полезная нагрузка | ||
+ | $i = $i - 1; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | С проверкой в конце цикла, а не в начале. Цикл в любом случае выполняется один раз: | ||
+ | <code powershell> | ||
+ | $i=8 | ||
+ | Do | ||
+ | { | ||
+ | $i; | ||
+ | $i = $i - 1; | ||
+ | } | ||
+ | while ($i -gt 0) # условие продолжения цикла | ||
+ | # если условие верно, цикл продолжается | ||
+ | </ | ||
+ | |||
+ | Выполнять цикл, пока не наступит условие: | ||
+ | <code powershell> | ||
+ | $i=8 | ||
+ | Do | ||
+ | { | ||
+ | $i; | ||
+ | $i = $i + 10; | ||
+ | } | ||
+ | until ($i -gt 1000) # условие окончания цикла | ||
+ | # если условие верно, цикл останавливается | ||
+ | </ | ||
+ | |||
+ | Цикл FOR - все условия задаются вне самого цикла, внутри - только полезная нагрузка. | ||
+ | <code powershell> | ||
+ | for ( | ||
+ | $i=8; # выполняется один раз при входе в цикл | ||
+ | $i -GT 0; # условие продолжения цикла | ||
+ | $i = $i - 1 # выполняется после каждого повторения | ||
+ | ) | ||
+ | { | ||
+ | $i; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Перебор (foreach) - для перебора существующего массива.\\ | ||
+ | Чтобы не городить конструкцию типа | ||
+ | <code powershell> | ||
+ | $srv=get-service | ||
+ | for ( | ||
+ | $i=0; # выполняется один раз при входе в цикл | ||
+ | $i -LT $srv.count; # условие продолжения цикла | ||
+ | $i = $i + 1 # выполняется после каждого повторения | ||
+ | ) | ||
+ | { | ||
+ | $srv[$i].Name; | ||
+ | } | ||
+ | </ | ||
+ | пишем | ||
+ | <code powershell> | ||
+ | $srv = get-service | ||
+ | foreach ($s in $srv) | ||
+ | { | ||
+ | $s.Name | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Условие (IF).\\ | ||
+ | Простой случай: | ||
+ | <code powershell> | ||
+ | $t = 8 | ||
+ | if ($t -gt 3) | ||
+ | { | ||
+ | Write-Host " | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Выполнить что-то другое, | ||
+ | <code powershell> | ||
+ | cls | ||
+ | $t = 2 | ||
+ | if ($t -gt 3) | ||
+ | { | ||
+ | Write-Host " | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | Write-Host "Не больше трёх" | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Несколько условий (if-elseif-else) | ||
+ | <code powershell> | ||
+ | $t = 1 | ||
+ | if ($t -gt 3) | ||
+ | { | ||
+ | Write-Host " | ||
+ | } | ||
+ | elseif ($t -eq 3) | ||
+ | { | ||
+ | Write-Host " | ||
+ | } | ||
+ | elseif ($t -eq 2) | ||
+ | { | ||
+ | Write-Host " | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | Write-Host " | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Найти каталог на C:\, в котором больше всего вложенных каталогов. | ||
+ | <code powershell> | ||
+ | $folder = c:\ | ||
+ | $dirs = dir $folder -Directory | ||
+ | foreach ($d in $dirs) | ||
+ | { | ||
+ | $subd = $d.GetDirectories().Count | ||
+ | if ($subd -gt $max) {$max = $subd; $dirname = $d.Name} | ||
+ | } | ||
+ | |||
+ | Write-Host $dirname | ||
+ | Write-Host $max | ||
+ | </ | ||
+ | |||
+ | ==== 13. Запуск сценария с параметрами ==== | ||
+ | Вместо задания переменной в коде вынести её в начало скрипта таким образом: | ||
+ | <code powershell> | ||
+ | Param( | ||
+ | [string]$folder | ||
+ | ) | ||
+ | </ | ||
+ | |||
+ | <code powershell> | ||
+ | # После этого можно передавать путь как параметр к скрипту. | ||
+ | .\script.ps1 C:\ | ||
+ | # Также, табом можно перебирать эти параметры, | ||
+ | .\script.ps1 -folder C:\ -extension exe | ||
+ | </ | ||
+ | |||
+ | Обязательные параметры: | ||
+ | <code powershell> | ||
+ | # Перед блоком Param() написать | ||
+ | [CmdletBinding()] | ||
+ | # Также, перед параметром поставить | ||
+ | [Parameter(Mandatory=$True)] | ||
+ | </ | ||
+ | |||
+ | Для необязательных параметров можно задать значение по умолчанию: | ||
+ | <code powershell> | ||
+ | [string]$extension = " | ||
+ | </ | ||
+ | |||
+ | Для заданной папки создать в каждой подпапке вложенную папку с названием " | ||
+ | <code powershell> | ||
+ | param( | ||
+ | $parent = "" | ||
+ | ) | ||
+ | |||
+ | # Создать | ||
+ | gci $parent -Directory | foreach {New-item -path ($_).FullName -Name Специалист -ItemType Directory} | ||
+ | # А можно вызывать метод напрямую: | ||
+ | gci $parent -Directory | foreach CreateSubDirectory Специалист | ||
+ | </ | ||
+ | |||
+ | ==== 15. Обработка ошибок ==== | ||
+ | <code powershell> | ||
+ | try { code } | ||
+ | catch { errors handling } | ||
+ | </ | ||
+ | |||
+ | Try и Catch должны идти последовательно друг за другом. Если в try всё в порядке, | ||
+ | <code powershell> | ||
+ | # Удалить | ||
+ | gci $parent -Directory -Recurse | where Name -like Специалист |Remove-Item | ||
+ | |||
+ | write-output | ||
+ | write-warning | ||
+ | write-error | ||
+ | write-verbose | ||
+ | write-debug | ||
+ | |||
+ | [CmdletBinding()] # даёт возможность показывать отладочную информацию write-verbose и write-debug. | ||
+ | # По умолчанию, | ||
+ | |||
+ | Param( | ||
+ | [int]$a, | ||
+ | [int]$b, | ||
+ | [switch]$c # такого типа нет, но если не указывать его как параметр скрипта, | ||
+ | # то будет false, если указывать - true. | ||
+ | ) | ||
+ | |||
+ | Write-Verbose ("A = " + $a) | ||
+ | Write-Verbose ("B = " + $b) | ||
+ | Write-Verbose ("C = " + $c) | ||
+ | |||
+ | # $error - переменная, | ||
+ | # $error |gm | ||
+ | # $error.categoryinfo | ||
+ | # $error.errordetails | ||
+ | |||
+ | $a = 0 | ||
+ | try { | ||
+ | $a + 1 | ||
+ | $a * 2 | ||
+ | 10 / $a | ||
+ | $a - 1 | ||
+ | Write-Output " | ||
+ | } | ||
+ | catch { | ||
+ | Write-Output " | ||
+ | $error | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== 16. Удалённое исполнение команд ==== | ||
+ | На удалённой машине должен работать сервис WinRM.\\ | ||
+ | Для настройки удалённого доступа выполнить команду winrm quickconfig на целевой машине. | ||
+ | |||
+ | Удалённый запуск команды: | ||
+ | Будут работать команды, | ||
+ | <code powershell> | ||
+ | Get-Service -ComputerName DC1, | ||
+ | |||
+ | # Запуск оболочки на удалённом компьютере: | ||
+ | Enter-PSSession DC1 | ||
+ | Exit-PSSession | ||
+ | |||
+ | # Для одновременного запуска на большом кол-ве машин: | ||
+ | Invoke-Command -ComputerName DC1, | ||
+ | </ | ||
+ | |||
+ | ==== 17. Фоновое выполнение команд ==== | ||
+ | <code powershell> | ||
+ | Start-Job {dir c:\ -recurse |measure-object} | ||
+ | # Каждой задаче присваивается ID, узнать их состояние можно командой | ||
+ | Get-Job | ||
+ | # Получить результат задачи, | ||
+ | Receive-Job -Id 2 | ||
+ | # Можно добавить его в переменную и использовать в дальнейшем | ||
+ | $s = Receive-Job -Id 2 | select -first 5 | ||
+ | |||
+ | get-command -noun Job | ||
+ | </ | ||
+ | |||
+ | ==== 18. Планировщик задач ==== | ||
+ | <code powershell> | ||
+ | get-command -noun scheduledjob | ||
+ | </ | ||
+ | |||
+ | ==== 19. Функции, | ||
+ | <code powershell> | ||
+ | Function set-myinfo | ||
+ | { | ||
+ | [cmdletbinding()] | ||
+ | Param( | ||
+ | [parameter(mandatory=$true)] | ||
+ | [string]$filename, | ||
+ | [parameter(mandatory=$true)] | ||
+ | [string]$text | ||
+ | ) | ||
+ | set-content -path $filename -value $text | ||
+ | } | ||
+ | |||
+ | Function get-myinfo { | ||
+ | [cmdletbinding()] | ||
+ | Param( | ||
+ | [parameter(mandatory=$true)] | ||
+ | [string]$filename | ||
+ | ) | ||
+ | get-content -path $filename | ||
+ | } | ||
+ | |||
+ | ################################## | ||
+ | # Вызов функции | ||
+ | set-myinfo -filename " | ||
+ | get-myinfo -filename " | ||
+ | </ | ||
+ | |||
+ | Из скрипта с функциями можно сделать модуль - расширение .psm1. Там нужно оставить только функции.\\ | ||
+ | Каталоги с модулями PS по умолчанию ($env: | ||
+ | <code powershell> | ||
+ | $env: | ||
+ | </ | ||
+ | В ней создать папку с именем модуля, | ||
+ | <code powershell> | ||
+ | $env: | ||
+ | |||
+ | import-module -listavailable | ||
+ | import-module modulename | ||
+ | </ | ||
+ | |||
+ | Далее можно вызывать функции в модуле как стандартные командлеты, | ||
+ | <code powershell> | ||
+ | get-command -noun myinfo | ||
+ | </ | ||
+ | |||
+ | Добавить справку в модуль: | ||
+ | <code powershell> | ||
+ | <# | ||
+ | .SYNOPSIS | ||
+ | Краткое описание | ||
+ | .DESCRIPTION | ||
+ | Подробное описание | ||
+ | .PARAMETER filename | ||
+ | Описание параметра | ||
+ | .PARAMETER text | ||
+ | Описание параметра | ||
+ | .EXAMPLE | ||
+ | примеры | ||
+ | #> | ||
+ | </ | ||
+ | |||
+ | === Запуск функции удалённо === | ||
+ | <code powershell> | ||
+ | # will NOT work: | ||
+ | Invoke-Command -ScriptBlock { Get-Software -DisplayName *Office* } -ComputerName server01 | ||
+ | # will work (provided server01 exists and is set up for remoting): | ||
+ | Invoke-Command -ScriptBlock ${function: | ||
+ | </ | ||
+ | https:// | ||
+ | |||
+ | |||
+ | ==== 21. AD ==== | ||
+ | <code powershell> | ||
+ | get-command -module activedirectory | ||
+ | dir ad: # список разделов | ||
+ | get-item " | ||
+ | </ | ||
+ | |||
+ | ==== 080 Параметр Verbose ==== | ||
+ | Чтобы не городить огород с логическими операторами и циклами типа | ||
+ | <code powershell> | ||
+ | Function List-Service { | ||
+ | [cmdletbinding()] | ||
+ | Param( | ||
+ | [string]$ServiceName = " | ||
+ | [parameter(mandatory=$true)] | ||
+ | [int]$Top | ||
+ | [switch]$Protocol | ||
+ | ) | ||
+ | if ($Protocol) { Write-Host " | ||
+ | get-service -name $servicename | select -first $top | ||
+ | if ($Protocol) { Write-Host " | ||
+ | } | ||
+ | |||
+ | # Запуск: | ||
+ | List-Service -Top 2 -Protocol | ||
+ | </ | ||
+ | |||
+ | имеется встроенный параметр -Verbose с подсветкой вывода, | ||
+ | <code powershell> | ||
+ | Function List-Service { | ||
+ | [cmdletbinding()] | ||
+ | Param( | ||
+ | [string]$ServiceName = " | ||
+ | [parameter(mandatory=$true)] | ||
+ | [int]$Top | ||
+ | ) | ||
+ | Write-Verbose " | ||
+ | get-service -name $servicename | select -first $top | ||
+ | Write-Verbose " | ||
+ | } | ||
+ | |||
+ | # Запуск: | ||
+ | List-Service -Top 2 -Verbose | ||
+ | </ | ||
+ | |||
+ | Параметр Verbose сквозной, | ||
+ | |||
+ | ==== 090 Синонимы для параметров ==== | ||
+ | Синоним (алиас) задаётся непосредственно перед каждым целевым параметром. | ||
+ | <code powershell> | ||
+ | Function mynewfunc { | ||
+ | [cmdletbinding()] | ||
+ | Param( | ||
+ | [Alias(' | ||
+ | [string]$MyString | ||
+ | ) | ||
+ | |||
+ | Write-Host $MyString | ||
+ | |||
+ | } | ||
+ | |||
+ | mynewfunc -str "Test string" | ||
+ | mynewfunc -ms "Test string" | ||
+ | </ | ||
+ | |||
+ | ==== 100 Проверка параметров ==== | ||
+ | <code powershell> | ||
+ | Function mynewfunc { | ||
+ | [cmdletbinding()] | ||
+ | Param( | ||
+ | [Alias(' | ||
+ | [ValidateLength(3, | ||
+ | [string]$MyString | ||
+ | ) | ||
+ | |||
+ | Write-Host $MyString | ||
+ | |||
+ | } | ||
+ | |||
+ | mynewfunc -ms "Test string" | ||
+ | mynewfunc -ms " | ||
+ | </ | ||
+ | |||
+ | <code powershell> | ||
+ | # Валидатор для числовых параметров: | ||
+ | [ValidateRange(3, | ||
+ | # Список вариантов: | ||
+ | [ValidateSet(' | ||
+ | </ | ||
+ | |||
+ | Сделать свой валидатор: | ||
+ | <code powershell> | ||
+ | [ValidateScript({if ($_ -gt 10) {$True} else {$False}})] | ||
+ | [int]$MyInt | ||
+ | mynewfunc -MyInt 9 # ошибка | ||
+ | mynewfunc -MyInt 11 # сработает | ||
+ | |||
+ | [ValidatePattern(' | ||
+ | [ValidateLength(3, | ||
+ | [string]$MyString | ||
+ | |||
+ | mynewfunc -MyString " | ||
+ | mynewfunc -MyString " | ||
+ | mynewfunc -MyString " | ||
+ | </ | ||
+ | |||
+ | ==== 110. Приём списков в качестве параметров ==== | ||
+ | <code powershell> | ||
+ | Function mylistfunc { | ||
+ | [cmdletbinding()] | ||
+ | Param( | ||
+ | [string[]]$FolderList | ||
+ | ) | ||
+ | foreach ($Folder in $FolderList) { | ||
+ | dir $Folder -Directory | measure | ||
+ | } | ||
+ | } | ||
+ | |||
+ | mylistfunc -folderlist " | ||
+ | </ | ||
+ | Если указать, | ||
+ | |||
+ | ==== 120. Приём параметров из конвейера ==== | ||
+ | <code powershell> | ||
+ | Function mylistfunc { | ||
+ | [cmdletbinding()] | ||
+ | Param( | ||
+ | [parameter(ValueFromPipeline=$True)] | ||
+ | [string[]]$FolderList | ||
+ | ) | ||
+ | BEGIN {} | ||
+ | PROCESS { | ||
+ | foreach ($Folder in $FolderList) { | ||
+ | dir $Folder -Directory | measure | ||
+ | } | ||
+ | } | ||
+ | END {} | ||
+ | } | ||
+ | |||
+ | gc .\folderslist.txt | mylistfunc | ||
+ | </ | ||
+ | |||
+ | Если просто добавить '' | ||
+ | |||
+ | ==== 130. Создание объектов ==== | ||
+ | PSObject - универсальный тип объекта | ||
+ | <code powershell> | ||
+ | function MyFunc1 { | ||
+ | $Properties = @{' | ||
+ | New-Object -TypeName PSObject -Property $Properties | ||
+ | } | ||
+ | |||
+ | cls | ||
+ | MyFunc1 | ||
+ | </ | ||
+ | |||
+ | ==== 140. Работа с объектами .NET ==== | ||
+ | Можно использовать классы .NET, если в PS нет соотв. команды, | ||
+ | <code powershell> | ||
+ | $test = New-Object -TypeName System.Net.HttpWebRequest | ||
+ | $test |gm | ||
+ | |||
+ | $d = New-Object -TypeName datetime | ||
+ | $d | ||
+ | $d = [datetime]' | ||
+ | $d | ||
+ | $d.AddDays(10) | ||
+ | $d.Year | ||
+ | $d.Month | ||
+ | $d.DayOfWeek | ||
+ | |||
+ | # 1 января 0001 г. 0:00:00 | ||
+ | # 3 декабря 2005 г. 0:00:00 | ||
+ | # 13 декабря 2005 г. 0:00:00 | ||
+ | # 2005 | ||
+ | # 12 | ||
+ | # Saturday | ||
+ | </ | ||
+ | |||
+ | ==== 150. Инструменты и управляющие сценарии ==== | ||
+ | При усложнении сценария целесообразно разбивать его на части. Рекомендуется делить программу на две группы - инструменты и управляющие сценарии. Инструменты решают конкретную задачу, | ||
+ | |||
+ | ==== 160. Директива Requires ==== | ||
+ | Проверка необходимых компонентов и условий для работы скрипта. Оформляется как комментарий. | ||
+ | <code powershell> | ||
+ | #Requires -Version 2.0 | ||
+ | #Requires -Module ActiveDirectory | ||
+ | #Requires -RunAsAdministrator | ||
+ | |||
+ | Get-Service | ||
+ | </ | ||
+ | |||
+ | ==== 170. Взаимодействие с пользователем ==== | ||
+ | <code powershell> | ||
+ | write-host # выводит информацию на экран | ||
+ | read-host # захватывает ввод пользователя | ||
+ | clear-host # очистка экрана (cls) | ||
+ | </ | ||
+ | <code powershell> | ||
+ | Write-Host " | ||
+ | Write-Host "1. Установить" | ||
+ | Write-Host "2. Удалить" | ||
+ | Write-Host "3. Запилить" | ||
+ | |||
+ | $r = Read-Host | ||
+ | if ($r -eq 1) { | ||
+ | Write-Host " | ||
+ | Write-Host "1. Полный" | ||
+ | Write-Host "2. Минимальный" | ||
+ | Write-Host "3. Отмена" | ||
+ | |||
+ | $r2 = Read-Host " | ||
+ | |||
+ | Write-Host "Вы выбрали $r -> $r2" | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== 180. Организация работы с главным меню ==== | ||
+ | <code powershell> | ||
+ | Do { | ||
+ | Clear-Host | ||
+ | |||
+ | Write-Host " | ||
+ | Write-Host "1. Установить" | ||
+ | Write-Host "2. Удалить" | ||
+ | Write-Host "3. Запилить" | ||
+ | |||
+ | $r = Read-Host | ||
+ | if ($r -eq 1) { | ||
+ | Write-Host " | ||
+ | Write-Host "1. Полный" | ||
+ | Write-Host "2. Минимальный" | ||
+ | Write-Host "3. Выбор компонентов" | ||
+ | Write-Host "4. Отмена" | ||
+ | |||
+ | $r2 = Read-Host " | ||
+ | |||
+ | Write-Host "Вы выбрали $r -> $r2" | ||
+ | |||
+ | Read-Host " | ||
+ | } | ||
+ | } | ||
+ | while ($r2 -ne 4) | ||
+ | </ | ||
+ | ==== 190. Генерация отчётов в HTML ==== | ||
+ | У ConvertTo-Html есть параметр -Fragment, который генерирует только содержимое без открывающих и закрывающих тэгов. | ||
+ | Таким образом, | ||
+ | При добавлении запрошенной информации в переменные полезно использовать команду Out-String, чтобы данные были одной строкой, | ||
+ | |||
+ | ==== 200. Обработка нештатных ситуаций ==== | ||
+ | 2 типа ошибок - останавливающая, | ||
+ | Имеется системная переменная $ErrorActionPreference со значением Continue по умолчанию, | ||
+ | <code powershell> | ||
+ | $ErrorActionPreference = " | ||
+ | # ошибки выводиться не будут, но это плохая практика. | ||
+ | |||
+ | $ErrorActionPreference = " | ||
+ | # спрашивать пользователя, | ||
+ | |||
+ | $ErrorActionPreference = " | ||
+ | # остановка обработки, | ||
+ | # Также, это позволяет перехватывать ошибки. | ||
+ | </ | ||
+ | Ключ -ErrorAction у каждого командлета позволяет задавать поведение для конкретного действия, | ||
+ | |||
+ | Для обработки ошибок используется конструкция | ||
+ | <code powershell> | ||
+ | try { code } | ||
+ | catch { errors handling } | ||
+ | finally { code } | ||
+ | </ | ||
+ | Try и Catch должны идти последовательно друг за другом. Если в try всё в порядке, | ||
+ | |||
+ | <code powershell> | ||
+ | try { dir C: | ||
+ | catch { Write-Warning " | ||
+ | finally { Write-Host " | ||
+ | </ | ||
+ | Без указания -ErrorAction Stop блок catch выполняться не будет. | ||
+ | |||
+ | Неплохо бы знать также, что за ошибка произошла и в каком месте. | ||
+ | <code powershell> | ||
+ | try { dir C: | ||
+ | catch { | ||
+ | Write-Warning " | ||
+ | $_ | gm # переменная с ошибкой, | ||
+ | $Error[0] # массив, | ||
+ | } | ||
+ | finally { Write-Host " | ||
+ | </ | ||
+ | |||
+ | -ErrorVariable может создавать переменную ошибки для каждой команды, | ||
+ | |||
+ | ==== 210. Работа с XML ==== | ||
+ | XML удобен тем, что хранит и данные, | ||
+ | <code xml> | ||
+ | <> # элемент, | ||
+ | <lan> | ||
+ | < | ||
+ | <addr ip=" | ||
+ | </ | ||
+ | </ | ||
+ | Атрибут чаще используется для неповторяющегося свойства, | ||
+ | |||
+ | ===== Getting Started with Microsoft PowerShell ===== | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | https:// | ||
+ | ==== Don't fear the shell ==== | ||
+ | |||
+ | * Cmdlets: verb-noun | ||
+ | * Native commands work - ping, ipconfig, calc, notepad, mspaint | ||
+ | * cls - Clear-Host | ||
+ | * cd - Set-Location | ||
+ | * dir, ls - Get-Childitem | ||
+ | * type, cat - Get-Content | ||
+ | * Copy, cp - Copy-Item | ||
+ | |||
+ | <code powershell> | ||
+ | Get-Alias *sv # список псевдонимов, | ||
+ | Get-Alias -Definition get-process # показать псевдонимы для get-process | ||
+ | # работает как в линуксе | ||
+ | cd / | ||
+ | cd ~ | ||
+ | </ | ||
+ | |||
+ | http:// | ||
+ | |||
+ | ==== The help system ==== | ||
+ | <code powershell> | ||
+ | update-help # обновить справку | ||
+ | get-help get-service # справка по get-service | ||
+ | get-help get-service -online # открыть онлайн-справку в браузере | ||
+ | get-help get-service -detailed # более подробная справка | ||
+ | get-help get-service -examples # примеры | ||
+ | get-help get-service -showwindow # открыть справку в отдельном окне | ||
+ | man get-service # то же самое | ||
+ | get-verb # глаголы, | ||
+ | </ | ||
+ | Синтаксис: | ||
+ | <code powershell> | ||
+ | Get-Service [[-Name] < | ||
+ | |||
+ | # Всё, что начинается с дефиса (-Name) - параметр | ||
+ | # <> - значение (аргумент) | ||
+ | # [] вокруг параметров и аргументов - это опциональный параметр | ||
+ | # [] вокруг самого параметра - можно писать сразу аргументы к командлету, | ||
+ | Get-Service bits | ||
+ | # или | ||
+ | gsv bits | ||
+ | # [] внутри <> - значение может быть множественным (разделённым запятыми) | ||
+ | </ | ||
+ | |||
+ | <code powershell> | ||
+ | Get-Service -Name b*, c* | ||
+ | Get-Service -DisplayName *bit* | ||
+ | get-eventlog -logname system -newest 3 -entrytype error -computername dc1, | ||
+ | get-help about* # список разъяснительных статей о разных вещах | ||
+ | get-help -Category CmdLet # вывести список статей по категории командлетов | ||
+ | </ | ||
+ | ; - разделитель типа && в линуксе (сделай это и потом сделай то) | ||
+ | |||
+ | http:// | ||
+ | |||
+ | ==== The pipeline: getting connected & extending the shell ==== | ||
+ | <code powershell> | ||
+ | get-service | export-csv -Path c: | ||
+ | import-csv c:/ | ||
+ | |||
+ | get-service | export-clixml -Path c: | ||
+ | |||
+ | Compare-Object -ReferenceObject (Import-Clixml c: | ||
+ | |||
+ | get-service | Out-file -filepath c: | ||
+ | get-content c: | ||
+ | |||
+ | get-service | Convertto-html -Property Name,Status | out-file c: | ||
+ | |||
+ | get-service -DisplayName *bi* | stop-service -whatif # А что будет если (без реального выполнения) | ||
+ | get-service -DisplayName *bi* | stop-service -confirm # подтверждение выполнения каждого совпадения | ||
+ | |||
+ | get-module -ListAvailable # доступные модули | ||
+ | get-module # уже загруженные модули | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | http:// | ||
+ | |||
+ | ==== Objects for the Admin ==== | ||
+ | <code powershell> | ||
+ | get-process | where {$_.handles -gt 900} # gt - greater than | sort handles | ||
+ | get-process | where handles -gt 900 # то же самое, но упрощённая версия без скобок | ||
+ | get-service | get-member # получить список методов и свойств командлета | ||
+ | get-eventlog -logname system -newest 5 | select -property eventid, timewritten, | ||
+ | |||
+ | # Пример парсинга xml (Ромео и Джульетта) | ||
+ | # https:// | ||
+ | # прочитать содержимое и задать переменную | ||
+ | $x = [xml](get-content .\r_and_j.xml) | ||
+ | # Вывести все реплики из 1 акта 1 сцены | ||
+ | $x.PLAY.Act[0].scene[0].SPEECH | ||
+ | # Подсчитать количество реплик, | ||
+ | $x.PLAY.Act.scene.SPEECH | group speaker | sort count -descending | ||
+ | |||
+ | get-history # история команд | ||
+ | |||
+ | get-service | where {$_.status -eq " | ||
+ | # То же самое, $PSItem - это $_ | ||
+ | get-service | where {$PSItem.status -eq " | ||
+ | get-service | where {$PSItem.status -eq " | ||
+ | |||
+ | # Разница в концепциях | ||
+ | # Плохо из-за того, что фильтрация после сортировки - бессмысленная работа | ||
+ | get-stuff | sort | where -somestuff | out-file | ||
+ | # Сортировка после фильтрации - гораздо лучше | ||
+ | get-stuff | where -somestuff | sort | out-file | ||
+ | |||
+ | |||
+ | </ | ||
+ | |||
+ | http:// | ||
+ | |||
+ | ==== The pipeline: deeper ==== | ||
+ | Что передаётся через пайп (конвейер): | ||
+ | |||
+ | <code powershell> | ||
+ | # посмотреть, | ||
+ | get-help get-service -full | ||
+ | |||
+ | -InputObject < | ||
+ | Specifies ServiceController objects representing the services to be retrieved. Enter a variable that contains the objects, or type a command or expression that gets the objects. You can also pipe a service object to this cmdlet. | ||
+ | |||
+ | Требуется? | ||
+ | Позиция? | ||
+ | Значение по умолчанию | ||
+ | Принимать входные данные конвейера? | ||
+ | Принимать подстановочные знаки? false | ||
+ | |||
+ | -Name < | ||
+ | Specifies the service names of services to be retrieved. Wildcards are permitted. By default, this cmdlet gets all of the services on the computer. | ||
+ | |||
+ | Требуется? | ||
+ | Позиция? | ||
+ | Значение по умолчанию | ||
+ | Принимать входные данные конвейера? | ||
+ | Принимать подстановочные знаки? | ||
+ | |||
+ | # благодаря совпадению имён параметров в разных командлетах возможны такие сочетания, | ||
+ | get-service | stop-process -whatif # когда имена сервисов передаются как имена процессов | ||
+ | get-process calc | dir # показать местонахождение calc.exe | ||
+ | |||
+ | # если параметры не совпадают, | ||
+ | get-adcomputer -filter * | get-service -name bits # это не сработает | ||
+ | # можно задать параметр, | ||
+ | get-adcomputer -filter * | select -property @{name=' | ||
+ | |||
+ | # Иногда бывает так, что командлет вообще не принимает параметров по конвейеру | ||
+ | # Это не сработает, | ||
+ | get-adcomputer -filter * | get-wmiobject -class win32_bios | ||
+ | # Тем не менее, у get-wmiobject есть параметр -ComputerName, | ||
+ | get-wmiobject -class win32_bios -ComputerName (get-adcomputer -filter * | Select -expandproperty name) | ||
+ | # Начиная с 3-ей версии Powershell, можно написать ту же команду короче: | ||
+ | get-wmiobject -class win32_bios -ComputerName (get-adcomputer -filter * ).name | ||
+ | # А можно и так ({} обозначает скрипт для выполнения), | ||
+ | get-adcomputer -filter * | get-wmiobject win32_bios -computername {$_.name} | ||
+ | # Также, существует более новый аналог get-wmiobject - get-ciminstance, | ||
+ | </ | ||
+ | |||
+ | http:// | ||
+ | ==== The PowerShell in the shell: remoting ==== | ||
+ | Как подключиться | ||
+ | <code powershell> | ||
+ | Enter-PSSession server1 | ||
+ | [Server1]: PS c: | ||
+ | </ | ||
+ | Включить возможность удалённого подключения | ||
+ | <code powershell> | ||
+ | Enable-PSRemoting | ||
+ | </ | ||
+ | Включить в политике: | ||
+ | Computer configuration/ | ||
+ | В Windows 2012 это включено по умолчанию. | ||
+ | |||
+ | <code powershell> | ||
+ | invoke-command -computername dc, | ||
+ | invoke-command -computername dc, | ||
+ | icm dc, | ||
+ | </ | ||
+ | Установить веб-доступ к powershell на удалённой машине | ||
+ | <code powershell> | ||
+ | install-windowsfeature WindowsPowershellWebAccess | ||
+ | get-help *pswa* | ||
+ | install-pswawebapplication | ||
+ | add-pswaauthorizationrule -computergroupname # какая группа машин имеет доступ | ||
+ | add-pswaauthorizationrule -usergroupname # какая группа пользователей имеет доступ | ||
+ | </ | ||
+ | |||
+ | http:// | ||
+ | ==== Getting prepared for automation ==== | ||
+ | **AllSigned** - абсолютно все скрипты должны быть подписаны\\ | ||
+ | **RemoteSigned** - должны быть подписаны все скрипты, | ||
+ | |||
+ | <code powershell> | ||
+ | # сделать самоподписанный сертификат | ||
+ | New-SelfSignedCertificate | ||
+ | # вывести все диски (в т. ч. поставщиков Powershell) | ||
+ | get-psdrive | ||
+ | # показать все сертификаты подписи кода и создать переменную $a | ||
+ | dir Cert: | ||
+ | # тут не понял | ||
+ | $cert = $a[0] | ||
+ | # посмотреть текущую политику выполнения | ||
+ | get-executionpolicy | ||
+ | # изменить её на AllSigned | ||
+ | set-executionpolicy " | ||
+ | </ | ||
+ | После этого обычный скрипт (test.ps1) не выполнится | ||
+ | <code powershell> | ||
+ | # Подписать скрипт test.ps1 | ||
+ | Set-AuthenticodeSignature -Certificate $cert -Filepath .\Test.ps1 | ||
+ | </ | ||
+ | Посде подписи в конец скрипта добавляется цифровая подпись, | ||
+ | |||
+ | === Переменные === | ||
+ | <code powershell> | ||
+ | get-help *variable* | ||
+ | |||
+ | $MyVar=" | ||
+ | $MyVar= get-service bits | ||
+ | $MyVar.status | ||
+ | $MyVar.stop() | ||
+ | $MyVar.refresh() # если не обновить, | ||
+ | $MyVar.status | ||
+ | |||
+ | # | ||
+ | $var=read-host " | ||
+ | get-service bits -computername $var | ||
+ | |||
+ | write-host $var -foregroundcolor red -backgroundcolor green | ||
+ | write-host $var | get-member # не сработает | ||
+ | </ | ||
+ | Write-host ничего не передаёт и вообще его использование не рекомендуется, | ||
+ | <code powershell> | ||
+ | write-output $var | get-member # а вот это сработает | ||
+ | </ | ||
+ | Цвет текста в консоли | ||
+ | <code powershell> | ||
+ | # предупреждение | ||
+ | write-warning " | ||
+ | write-error " | ||
+ | </ | ||
+ | Тем не менее, следует не увлекаться тем, что // | ||
+ | |||
+ | Переменные можно задавать любые, в том числе, с пробелами и неанглийские, | ||
+ | <code powershell> | ||
+ | ${привет, | ||
+ | </ | ||
+ | Если задать переменной путь к файлу, то он вернёт содержимое | ||
+ | <code powershell> | ||
+ | 1..5 > C: | ||
+ | ${C: | ||
+ | 1 | ||
+ | 2 | ||
+ | 3 | ||
+ | 4 | ||
+ | 5 | ||
+ | </ | ||
+ | Но если задать переменной значение, | ||
+ | <code powershell> | ||
+ | ${C: | ||
+ | </ | ||
+ | |||
+ | http:// | ||
+ | ==== Automation in scale: remoting ==== | ||
+ | Особенность запуска удалённого кода в том, что после того, как он отработает, | ||
+ | |||
+ | Это не сработает, | ||
+ | <code powershell> | ||
+ | icm -comp dc {$var=2} | ||
+ | icm -comp dc {write-output $var} | ||
+ | </ | ||
+ | |||
+ | Правильный вариант - обращаться в ту же сессию, | ||
+ | <code powershell> | ||
+ | $sessions=new-pssession -computername dc | ||
+ | icm -session $sessions {$var=2} | ||
+ | icm -session $sessions {$var} | ||
+ | |||
+ | # можно померить время, за которое выполняется команда | ||
+ | measure-command {icm -computername dc {get-process}} | ||
+ | # это должно быть быстрее | ||
+ | measure-command {icm -session $sessions {get-process}} | ||
+ | </ | ||
+ | |||
+ | <code powershell> | ||
+ | # Взять два сервера | ||
+ | $servers= ' | ||
+ | # убедиться, | ||
+ | $servers | foreach {start iexplore http://$_} | ||
+ | # сделать переменную для сессий | ||
+ | $sessions=new-pssession -computername $servers | ||
+ | # поставить IIS | ||
+ | icm -session $sessions {install-windowsfeature web-server} | ||
+ | # теперь проверка будет положительной | ||
+ | $servers | foreach {start iexplore http://$_} | ||
+ | # можно создать " | ||
+ | notepad c: | ||
+ | $servers | foreach {copy-item c: | ||
+ | </ | ||
+ | |||
+ | Удалённые сессии полезны ещё и потому, | ||
+ | <code powershell> | ||
+ | $s=new-pssession -computername dc | ||
+ | import-pssession -session $s -module activedirectory -prefix remote | ||
+ | </ | ||
+ | После этого командлеты AD становятся доступны на локальной машине, | ||
+ | <code powershell> | ||
+ | get-remoteadcomputer -filter * | ||
+ | </ | ||
+ | Но по факту всё это выполняется удалённо, | ||
+ | |||
+ | Просмотр параметров командлетов | ||
+ | <code powershell> | ||
+ | $c = get-command get-process | ||
+ | $c.parameters | ||
+ | $c.parameters[" | ||
+ | </ | ||
+ | |||
+ | Если посмотреть определение удалённого командлета, | ||
+ | <code powershell> | ||
+ | (get-command get-remoteadcomputer).definition | ||
+ | </ | ||
+ | |||
+ | Присвоение префикса командлету | ||
+ | <code powershell> | ||
+ | $s = nsn | ||
+ | import-session $s -commandname get-process -prefix wow | ||
+ | get-wowprocess | ||
+ | </ | ||
+ | |||
+ | http:// | ||
+ | ==== Introducing scripting and toolmaking ==== | ||
+ | Если нажать в Powershell ISE сочетание Ctrl+Space, то это может показать классы WMI. | ||
+ | <code powershell> | ||
+ | Get-CimInstance Wind32_Logical# | ||
+ | </ | ||
+ | После пайпа можно нажать Enter, и в интерактивном режиме команду можно продолжать набирать. | ||
+ | <code powershell> | ||
+ | Get-WmiObject win32_logicaldisk -filter " | ||
+ | >> Select @{n=' | ||
+ | </ | ||
+ | Задать параметр: | ||
+ | <code powershell> | ||
+ | param( | ||
+ | $Computername=' | ||
+ | $bogus | ||
+ | ) | ||
+ | Get-WmiObject -computername $Computername win32_logicaldisk -filter " | ||
+ | </ | ||
+ | Эти параметры можно выбирать после запуска сохранённого скрипта клавишей Tab и задавать их на лету. | ||
+ | |||
+ | После сохранения скрипта с параметрами и вызова этого скрипта через get-help, вывод выглядит как спавка к командлету, | ||
+ | <code powershell> | ||
+ | [string]$Computername | ||
+ | </ | ||
+ | , то параметр будет иметь значение " | ||
+ | <code powershell> | ||
+ | [string[]]$Computername=' | ||
+ | </ | ||
+ | Если в начале скрипта добавить | ||
+ | <code powershell> | ||
+ | [CmdletBinding()] | ||
+ | </ | ||
+ | , то будут доступны все прочие параметры [< | ||
+ | |||
+ | Если в список параметров добавить | ||
+ | <code powershell> | ||
+ | param( | ||
+ | [Parameter(Mandatory=$True)] | ||
+ | </ | ||
+ | , то следующий за ним параметр (один), будет обязательным. | ||
+ | |||
+ | http:// | ||
+ | |||
+ | ===== Learn Windows Powershell in a month of lunches (3rd edition), краткий конспект ===== | ||
+ | Поезные ресурсы: | ||
+ | https:// | ||
+ | https:// | ||
+ | <code powershell> | ||
+ | # Узнать установленную версию (v4 и выше) | ||
+ | $PSVersionTable | ||
+ | </ | ||
+ | |||
+ | ==== Справка ==== | ||
+ | <code powershell> | ||
+ | help Get-Service # Получить справку по Get-Service | ||
+ | Update-Help # Обновить справку | ||
+ | Save-Help # Сохранить справку локально | ||
+ | Update-Help -Source path # Загрузить справку из локального источника | ||
+ | help *log* # найти командлеты, | ||
+ | help Get-Service -ShowWindow # показать справку в отдельном окне | ||
+ | help Get-Service -Online # показать справку в интернете | ||
+ | Help Get-EventLog -example # показать примеры использования | ||
+ | Help about_* # список справочной информации по областям применения | ||
+ | </ | ||
+ | |||
+ | === Интерпретация синтаксиса справки === | ||
+ | <code powershell> | ||
+ | Get-EventLog [-LogName] < | ||
+ | [-Before < | ||
+ | [-Message < | ||
+ | |||
+ | Get-EventLog [-AsString] [-ComputerName < | ||
+ | </ | ||
+ | В данном случае есть два набора параметров, | ||
+ | [< | ||
+ | [ ] - необязательный (optional) параметр.\\ | ||
+ | Positional parameter - обязательный параметр, | ||
+ | <code powershell> | ||
+ | Get-EventLog System -Newest 20 | ||
+ | </ | ||
+ | Выяснить свойства параметров можно в полной справке по командлету с ключом -Full. | ||
+ | === Значения параметров === | ||
+ | Параметр " | ||
+ | |||
+ | Типы вводных данных: | ||
+ | Строка (String) - ряд букв и цифр. Если с пробелами (типа C:\Program Files), то нужно заключать в одинарные кавычки (' ').\\ | ||
+ | Целые числа (Int, Int32, Int64) - без десятичных значений.\\ | ||
+ | Дата и время (DataTime) - строка, | ||
+ | |||
+ | Квадратные скобки, | ||
+ | <code powershell> | ||
+ | Get-EventLog Security -computer Server-R2, | ||
+ | </ | ||
+ | Множественное значение может быть прочитано из файла, например | ||
+ | <code powershell> | ||
+ | Get-EventLog Application -computer (Get-Content names.txt) | ||
+ | </ | ||
+ | Если параметр обязательный, | ||
+ | |||
+ | ==== Запуск команд ==== | ||
+ | Не интерпретировать параметры, | ||
+ | <code powershell> | ||
+ | C: | ||
+ | </ | ||
+ | |||
+ | ==== Провайдеры (providers) ==== | ||
+ | Провайдеры - это хранилища информации, | ||
+ | <code powershell> | ||
+ | Get-PSProvider # вывести список доступных провайдеров | ||
+ | </ | ||
+ | Для работы с провайдерами по большей части используются командлеты, | ||
+ | <code powershell> | ||
+ | Get-Command -noun *item* | ||
+ | </ | ||
+ | Суть в том, что можно запрашивать любые объекты провайдера одними и теми же командлетами. | ||
+ | <code powershell> | ||
+ | Set-Location -Path C:\Windows # файловая система | ||
+ | Set-Location -Path hkcu: # реестр | ||
+ | Set-Location -Path Env: # системные переменные | ||
+ | # если не указать тип, то PS спросит об этом, т. к. непонятен тип объекта | ||
+ | New-Item TestFolder -Type Directory | ||
+ | </ | ||
+ | По умолчанию, | ||
+ | |||
+ | Можно выгружать информацию в CSV и XML с помощью командлетов Export-CliXML и Export-Csv. в XML выгружается больше подробностей. Подобную выгрузку можно использовать для сравнения, | ||
+ | <code powershell> | ||
+ | Diff -reference (Import-CliXML reference.xml) -difference (Get-Process) -property Name | ||
+ | </ | ||
+ | Если выпустить -Property, то сравнение будет идти по всем полям. Diff в Powershell не очень хорошо работает для сравнения текстовых файлов. | ||
+ | |||
+ | <code powershell> | ||
+ | # Тупо выгрузить в файл | ||
+ | Dir > DirectoryList.txt | ||
+ | # А вот здесь можно задать параметры выгрузки - кодировка, | ||
+ | Dir | Out-File DirectoryList.txt | ||
+ | |||
+ | help out* # посмотреть, | ||
+ | get-service | out-printer # напечатать список служб | ||
+ | Get-Service | ConvertTo-HTML > services.html # создать HTML-страничку со списком служб | ||
+ | </ | ||
+ | |||
+ | У командлетов есть определённый // | ||
+ | <code powershell> | ||
+ | # Можно форсировать запросы подтверждения | ||
+ | Get-Service | Stop-Service -confirm | ||
+ | # Эмуляция выполнения | ||
+ | Get-Service | Stop-Service -whatif | ||
+ | </ | ||
+ | |||
+ | Отличие Import-CSV от Get-Content: | ||
+ | <code powershell> | ||
+ | # Без комментария о типе файла, не перезаписывать сущ. файл, | ||
+ | # использовать в качестве разделителя региональные параметры, | ||
+ | Get-Service | Export-CSV services.csv -NoTypeInformation -NoClobber -UseCulture -Confirm | ||
+ | </ | ||
+ | |||
+ | ==== Расширения ==== | ||
+ | Два типа расширений: | ||
+ | <code powershell> | ||
+ | # вывести список установленных, | ||
+ | get-pssnapin –registered | ||
+ | # загрузить оснастку (указать имя) | ||
+ | add-pssnapin sqlservercmdletsnapin100 | ||
+ | # Вывести список команд, | ||
+ | Get-Command -pssnapin sqlservercmdletsnapin100 | ||
+ | </ | ||
+ | Оснастка может добавить новых провайдеров, | ||
+ | |||
+ | Чтобы загружать нужные оснастки прямо при запуске PS, нужно загрузить эти оснастки, | ||
+ | <code powershell> | ||
+ | Export-Console c: | ||
+ | # Загрузить PS уже с нужными оснастками | ||
+ | %windir%\system32\WindowsPowerShell\v1.0\powershell.exe -noexit -psconsolefile c: | ||
+ | </ | ||
+ | Модули в этом способе не участвуют. | ||
+ | |||
+ | У модулей есть системная переменная modulepath, где прописаны пути к их местоположению. | ||
+ | <code powershell> | ||
+ | get-content env: | ||
+ | get-module # список модулей | ||
+ | import-module # загрузить модуль | ||
+ | </ | ||
+ | С 3-й версии PS нужно прописывать путь в переменной, | ||
+ | |||
+ | Для автозагрузки модулей при старте PS есть механизм // | ||
+ | - Сделать подпапку WindowsPowerShell в " | ||
+ | - В этом файле прописать все нужные команды Add-PSSnapin и Import-Module для загрузки нужных расширений. | ||
+ | - В PS от админа выполнить команду< | ||
+ | - Переоткрыть PS, после этого profile.ps1 будет загружен автоматически. | ||
+ | |||
+ | Галерея модулей: | ||
+ | |||
+ | ==== Объекты ==== | ||
+ | Если вывести Get-Process, | ||
+ | <code powershell> | ||
+ | Get-Process | ConvertTo-HTML | Out-File processes.html | ||
+ | </ | ||
+ | Собственно, | ||
+ | // | ||
+ | // | ||
+ | // | ||
+ | <code powershell> | ||
+ | Get-Process | Get-Member # (или gm) показать свойства и методы командлета | ||
+ | </ | ||
+ | К примеру, | ||
+ | <code powershell> | ||
+ | # передать через пайп | ||
+ | Get-Process -Name Notepad | Stop-Process | ||
+ | # или обойтись одним командлетом | ||
+ | Stop-Process -name Notepad | ||
+ | </ | ||
+ | === Сортировка === | ||
+ | <code powershell> | ||
+ | Get-Process | Sort-Object -property VM | ||
+ | Get-Process | Sort VM -desc # сокращённо и в обратном порядке | ||
+ | # Если несколько процессов занимают одинаковое кол-во памяти, | ||
+ | Get-Process | Sort VM,ID -desc | ||
+ | </ | ||
+ | === Выбор свойств === | ||
+ | Select-Object можно написать как просто select. | ||
+ | <code powershell> | ||
+ | Get-Process | Select-Object -property Name, | ||
+ | Get-Process | Select -First 10 # 10 первых, | ||
+ | </ | ||
+ | Нужно не путать Select-Object (выбор свойств для отображения) с Where-Object (фильтрует объекты после пайпа на основании заданных критериев). | ||
+ | |||
+ | ==== Ещё про пайп ==== | ||
+ | Положим, | ||
+ | <code powershell> | ||
+ | Get-Content .\computers.txt | Get-Service | ||
+ | </ | ||
+ | Это нзывается привязкой параметров (parameter binding). PS смотрит на тип полученных данных и далее применяет его к параметру второй команды, | ||
+ | |||
+ | В большинстве случаев, | ||
+ | <code powershell> | ||
+ | get-process -name note* | Stop-Process | ||
+ | </ | ||
+ | |||
+ | Если привязка по значению (ByValue) не удаётся, | ||
+ | <code powershell> | ||
+ | get-service -name s* | stop-process | ||
+ | </ | ||
+ | В данном примере, | ||
+ | |||
+ | Более успешный пример - создать файл .csv cо следующим содержанием: | ||
+ | <file csv aliases.csv> | ||
+ | Name,Value | ||
+ | d, | ||
+ | sel, | ||
+ | go, | ||
+ | </ | ||
+ | |||
+ | Если выполнить Get-Member, то можно узнать, | ||
+ | <code powershell> | ||
+ | import-csv .\aliases.csv | gm | ||
+ | </ | ||
+ | Далее, если выполнить | ||
+ | <code powershell> | ||
+ | import-csv .\aliases.csv | new-alias | ||
+ | </ | ||
+ | то окажется, | ||
+ | === Замена параметров при передаче === | ||
+ | Например, | ||
+ | <file csv newusers.csv> | ||
+ | login, | ||
+ | DonJ,IT,Las Vegas,CTO | ||
+ | GregS, | ||
+ | JeffH, | ||
+ | </ | ||
+ | Для создания пользователей используется New-ADUser, но там нет параметров dept и т. д., то есть, просто передать данные в сыром виде через пайп не получится. Для этого нужно указать соответствие передаваемых параметров. | ||
+ | <code powershell> | ||
+ | import-csv .\newusers.csv | select-object -property *, | ||
+ | >> @{name=' | ||
+ | >> @{label=' | ||
+ | >> @{n=' | ||
+ | </ | ||
+ | -property * - вывести все доступные свойства.\\ | ||
+ | @{key=value} - создание хэш-таблиц соответствия. Ключ может указываться как Name, N, Label или L. Значение - как Expression или E.\\ | ||
+ | $_ - обращение к исходному объекту, | ||
+ | === Скобки === | ||
+ | Некоторые командлеты не принимают данные через пайп, например, | ||
+ | <code powershell> | ||
+ | # Так работать не будет: | ||
+ | get-content .\computers.txt | get-wmiobject -class win32_bios | ||
+ | # А так - будет: | ||
+ | Get-WmiObject -class Win32_BIOS -ComputerName (Get-Content .\computers.txt) | ||
+ | </ | ||
+ | Необходимо, | ||
+ | <code powershell> | ||
+ | # Так работать не будет, в скобках тип будет ADComputer, | ||
+ | # а нужно String: | ||
+ | Get-Service -computerName (Get-ADComputer -filter * -searchBase " | ||
+ | # А так - будет (передать только имена): | ||
+ | Get-Service -computerName (Get-ADComputer -filter * -searchbase " | ||
+ | # -expand - вывести значения без названия столбца | ||
+ | </ | ||
+ | |||
+ | ==== Форматирование ==== | ||
+ | В папке $pshome есть файл otnettypes.format.ps1xml, | ||
+ | <code powershell> | ||
+ | Get-Process | gm | ||
+ | </ | ||
+ | скопировать тип (System.Diagnostics.Process) и поискать его в файле otnettypes.format.ps1xml, | ||
+ | |||
+ | В некоторых случаях предустановленный вывод отсутствует, | ||
+ | <code powershell> | ||
+ | Get-WmiObject Win32_OperatingSystem | Gm | ||
+ | </ | ||
+ | Такого типа данных нет в otnettypes.format.ps1xml, | ||
+ | |||
+ | " | ||
+ | === Команды форматирования === | ||
+ | **Format-Table (ft)** - таблица.\\ | ||
+ | -AutoSize - подгоняет ширину столбцов под длину строк.\\ | ||
+ | -Property - выбор столбцов для отображения, | ||
+ | Примеры: | ||
+ | <code powershell> | ||
+ | Get-Process | Format-Table -property * | ||
+ | Get-Process | Format-Table -property ID, | ||
+ | Get-Process | Format-Table * -autoSize | ||
+ | </ | ||
+ | -groupby - сортировка по какому-то из столбцов.\\ | ||
+ | -Wrap - перенос строк в столбце. | ||
+ | |||
+ | **Format-List (fl)** - список. Используются те же параметры, | ||
+ | В какой-то степени fl можно использовать как gm, с той разницей, | ||
+ | <code powershell> | ||
+ | Get-Service | Fl * | ||
+ | </ | ||
+ | |||
+ | **Format-Wide (fw)** - широкий список. Выводит только одно свойство (-Property), | ||
+ | <code powershell> | ||
+ | Get-Process | Format-Wide name -col 4 | ||
+ | </ | ||
+ | |||
+ | Более комплексные примеры: | ||
+ | <code powershell> | ||
+ | Get-Service | Format-Table @{name=' | ||
+ | Get-Process | Format-Table Name, | ||
+ | Get-Process | Format-Table Name, | ||
+ | </ | ||
+ | formatstring - код стандартного форматирования чисел и дат ([[https:// | ||
+ | -Width - задаваемая ширина столбца.\\ | ||
+ | align - выравнивание. | ||
+ | === Вывод === | ||
+ | Если используется команда, | ||
+ | <code powershell> | ||
+ | Get-Service | Format-Wide | Out-Host | ||
+ | Get-Service | Format-Wide | ||
+ | </ | ||
+ | Можно вывести данные в файл и на принтер, | ||
+ | Также, есть команда Out-GridView, | ||
+ | |||
+ | Команды форматирования (Format-*) должны идти последними в строке, | ||
+ | <code powershell> | ||
+ | Get-Service | Select Name, | ||
+ | </ | ||
+ | |||
+ | Для корректной обработки данных, | ||
+ | |||
+ | ==== Фильтр результатов и сравнение ==== | ||
+ | Два подхода: | ||
+ | Для последующей фильтрации используется команда Where-Object (where). | ||
+ | |||
+ | === Операторы сравнения === | ||
+ | -eq - Equality\\ | ||
+ | -ne - Not equal to\\ | ||
+ | -ge - Greater than or equal to\\ | ||
+ | -le - Less than or equal to\\ | ||
+ | -gt - Greater than\\ | ||
+ | -lt - Less than | ||
+ | |||
+ | Для сравнения нескольких строк одновременно используются -and и -or. Например, | ||
+ | Оператор -not меняет True или False на противоположное значение. Например, | ||
+ | <code powershell> | ||
+ | $_.Responding -eq $False | ||
+ | # можно написать как | ||
+ | -not $_.Responding | ||
+ | |||
+ | # Ещё пример фильтра | ||
+ | Get-ADComputer -Filter 'Name -notlike " | ||
+ | </ | ||
+ | Иногда -not пишется как !. | ||
+ | |||
+ | -like - понимает маски, например %%" | ||
+ | -match - сравнение текстовой строки и регулярного выражения. Противоположный оператор - -notmatch. | ||
+ | |||
+ | Если нужно использовать чувствительные к регистру операторы, | ||
+ | <code powershell> | ||
+ | # Справка | ||
+ | help about_comparison_operators | ||
+ | </ | ||
+ | Примеры использования фильтрации уже полученных результатов: | ||
+ | <code powershell> | ||
+ | Get-Service | Where Status -eq ' | ||
+ | get-service | where-object {$_.status -eq ' | ||
+ | </ | ||
+ | |||
+ | ==== Удалённый доступ ==== | ||
+ | <code powershell> | ||
+ | # Включить на целевой машине | ||
+ | Enable-PSRemoting | ||
+ | # Справка: | ||
+ | about_remote_troubleshooting | ||
+ | </ | ||
+ | Иногда советуют запускать Set-WSManQuickConfig, | ||
+ | |||
+ | Менять номер порта не рекомендуется, | ||
+ | <code powershell> | ||
+ | Winrm set winrm/ | ||
+ | @{Port=" | ||
+ | </ | ||
+ | |||
+ | === Два способа подключения: | ||
+ | 1:1 как RDP, только консоль. | ||
+ | <code powershell> | ||
+ | Enter-PSSession -computerName Server-R2 | ||
+ | [server-r2] PS C:\> | ||
+ | # Выйти: | ||
+ | Exit-PSSession | ||
+ | </ | ||
+ | Ограничения: | ||
+ | - PS-профили, | ||
+ | - Удалённая сессия будет ограничена политикой выполнения (execution policy) удалённой машины, | ||
+ | |||
+ | Без крайней необходимости лучше не запускать удалённые сессии из-под удалённых сессий (remoting chain), т. к. это трудно отслеживать. Иногда это бывает нужно, например, | ||
+ | |||
+ | One-to-many (1:N) - каждый комп запускает команду у себя и возвращает результат. | ||
+ | <code powershell> | ||
+ | Invoke-Command -computerName Server-R2, | ||
+ | -command { Get-EventLog Security -newest 200 | | ||
+ | Where { $_.EventID -eq 1212 }} | ||
+ | # Вместо -command можно использовать -scriptblock, | ||
+ | </ | ||
+ | По умолчанию PS запускает 32 удалённых запроса одновременно, | ||
+ | <code powershell> | ||
+ | # Запуск команды на серверах в списке | ||
+ | Invoke-Command -command { dir } | ||
+ | -computerName (Get-Content webservers.txt) | ||
+ | # Взять список из AD (нужен RSAT на клиенте) | ||
+ | Invoke-Command -command { dir } -computerName ( | ||
+ | Get-ADComputer -filter * -searchBase " | ||
+ | Select-Object -expand Name ) | ||
+ | </ | ||
+ | |||
+ | === Разница между Invoke-Command и -computerName === | ||
+ | <code powershell> | ||
+ | Get-EventLog Security -newest 200 | ||
+ | -computerName Server-R2, | ||
+ | | Where { $_.EventID -eq 1212 } | ||
+ | </ | ||
+ | - Команда запускается последовательно на каждой машине. не параллельно. | ||
+ | - В выводе нет свойства PSComputerName, | ||
+ | - WinRM не используется, | ||
+ | - Фильтр по событию 1212 применяется уже после запроса, | ||
+ | - События являются объектами, | ||
+ | |||
+ | <code powershell> | ||
+ | Invoke-Command -computerName Server-R2, | ||
+ | -command { Get-EventLog Security -newest 200 | | ||
+ | Where { $_.EventID -eq 1212 }} | ||
+ | </ | ||
+ | - Команда запускается одновременно на всех машинах, | ||
+ | - В выводе есть свойство PSComputerName, | ||
+ | - Используется WinRM, проще сделать правила на файрволлах между клиентом и серверами. | ||
+ | - Фильтрация происходит на серверах, | ||
+ | - Перед передачей на клиента, | ||
+ | |||
+ | === Локальная и удалённая обработка === | ||
+ | <code powershell> | ||
+ | # Фильтрация на удалённых серверах | ||
+ | Invoke-Command -computerName Server-R2, | ||
+ | -command { Get-EventLog Security -newest 200 | | ||
+ | Where { $_.EventID -eq 1212 }} | ||
+ | # Фильтрация на клиенте (плохая идея) | ||
+ | Invoke-Command -computerName Server-R2, | ||
+ | -command { Get-EventLog Security -newest 200 } | | ||
+ | Where { $_.EventID -eq 1212 } | ||
+ | </ | ||
+ | <code powershell> | ||
+ | # Работать не будет, т.к. результат выдачи с сервера - не объект | ||
+ | Invoke-Command -computerName Server-R2 | ||
+ | -command { Get-Process -name Notepad } | | ||
+ | Stop-Process | ||
+ | # Сработает | ||
+ | Invoke-Command -computerName Server-R2 | ||
+ | -command { Get-Process -name Notepad | | ||
+ | Stop-Process } | ||
+ | </ | ||
+ | <code powershell> | ||
+ | # На локальной машине доступны методы | ||
+ | get-service | get-member | ||
+ | # Здесь методов не будет, потому что вывод - не объекты | ||
+ | Invoke-Command -ScriptBlock { Get-Service } -ComputerName | ||
+ | server2 | Get-Member | ||
+ | </ | ||
+ | |||
+ | === Настройки удалённой сессии === | ||
+ | Параметр -SessionOption при запуске Invoke-Command или Enter-PSSession. | ||
+ | - Задаёт таймауты сессий | ||
+ | - Выключает сжатие и шифрование данных | ||
+ | - Пропуск проверки SSL-сертификатов, | ||
+ | <code powershell> | ||
+ | Enter-PSSession -ComputerName server2 | ||
+ | -SessionOption (New-PSSessionOption -SkipCNCheck) | ||
+ | </ | ||
+ | |||
+ | === Примечания === | ||
+ | * Удалённые сессии работают с реальными именами компьютеров - IP и алиасы использовать нельзя. | ||
+ | * Конфигурация по умолчанию рассчитана на домен, если что - надо читать help about_remote_troubleshooting, | ||
+ | * Invoke-Command - это значит, | ||
+ | * Для успешной работы нужно убедиться, | ||
+ | * Enable-PSRemoting создаёт правило только для Windows firewall, другие файрволлы надо настраивать отдельно. | ||
+ | * GPO перекрывает локальные настройки, | ||
+ | |||
+ | Рекомендуется книга [[https:// | ||
+ | |||
+ | ==== WMI и CIM ==== | ||
+ | WMI содержит пространства имён (namespaces), | ||
+ | Также, WMI содержит классы - управляемые компоненты, | ||
+ | Product в root\SecurityCenter, | ||
+ | <code powershell> | ||
+ | Get-CimInstance -Namespace root/ | ||
+ | |||
+ | displayName | ||
+ | instanceGuid | ||
+ | pathToSignedProductExe | ||
+ | pathToSignedReportingExe : C:\Program Files (x86)\Kaspersky Lab\Kaspersky Endpoint Security for Windows\x64\wmi64.exe | ||
+ | productState | ||
+ | timestamp | ||
+ | PSComputerName | ||
+ | |||
+ | displayName | ||
+ | instanceGuid | ||
+ | pathToSignedProductExe | ||
+ | pathToSignedReportingExe : %ProgramFiles%\Windows Defender\MsMpeng.exe | ||
+ | productState | ||
+ | timestamp | ||
+ | PSComputerName | ||
+ | </ | ||
+ | |||
+ | Просматривать репозиторий WMI удобно с помощью [[https:// | ||
+ | <code powershell> | ||
+ | Get-WmiObject -Namespace root/CIMV2 -list |where name -match ' | ||
+ | </ | ||
+ | |||
+ | WIM-команды, | ||
+ | |||
+ | <code powershell> | ||
+ | # Вывести все классы в пространстве имён cimv2 | ||
+ | Get-WmiObject -namespace root\cimv2 -list | ||
+ | # Содержимое класса win32_desktop | ||
+ | Get-WmiObject -namespace root\cimv2 -class win32_desktop | ||
+ | Get-WmiObject win32_desktop # или так | ||
+ | # использование алиаса | ||
+ | gwmi antispywareproduct -namespace root\securitycenter2 | ||
+ | # методы и свойства класса | ||
+ | gwmi win32_operatingsystem | gm | ||
+ | # фильтр | ||
+ | gwmi win32_desktop -filter " | ||
+ | </ | ||
+ | * Операторы сравнения не как в PS (-like, -eq), а =, <, >= и т. д. Можно использовать LIKE, и как указатель wildcard нужно писать не *, а %, например, | ||
+ | * Строки сравнения - в одиночных кавычках, | ||
+ | * Обратная косая черта (\) - экранирующий знак, если нужно поставить в строке \, то придётся удваивать - \\. | ||
+ | * Вывод gwmi всегда содержит ряд системных свойств, | ||
+ | <code powershell> | ||
+ | # выполняется последовательно, | ||
+ | Gwmi Win32_BIOS -comp server-r2, | ||
+ | # вариант с форматированием и названием колонок | ||
+ | gwmi win32_bios -computer server-r2, | ||
+ | ft @{label=' | ||
+ | @{label=' | ||
+ | @{label=' | ||
+ | -computer $_.__SERVER | select -expand BuildNumber}} –autosize | ||
+ | </ | ||
+ | |||
+ | Отличия Get-CimInstance от Get-WmiObject: | ||
+ | - Используется -ClassName, а не -Class | ||
+ | - Нет параметра -List, вместо этого нужно использовать Get-CimClass с параметром -Namespace | ||
+ | - Нет параметра -Credential, | ||
+ | |||
+ | Особенность работы с WMI в Powershell - справка малоэффективна, | ||
+ | |||
+ | ==== Несколько задач одновременно, | ||
+ | В обычном режиме команды запускаются // | ||
+ | * В синхронном режиме можно отвечать на возникающие запросы, | ||
+ | * В синхронном режиме сразу появляются сообщения об ошибках, | ||
+ | * PS в синхронном режиме запрашивает значения обязательных параметров, | ||
+ | * Результаты выполнения задачи в синхронном режиме отображаются сразу же, в асинхронном - после выполнения задачи доступны в кэше. | ||
+ | |||
+ | В фоне нужно запускать только хорошо отлаженные сценарии, | ||
+ | |||
+ | <code powershell> | ||
+ | # Запустить задачу | ||
+ | Start-Job -ScriptBlock {dir} -Name Job1 -Credential DOMAIN\Username | ||
+ | # Задача из файла, на другой машине | ||
+ | Start-Job -FilePath C: | ||
+ | </ | ||
+ | Все эти задачи называются локальными, | ||
+ | |||
+ | У Get-WmiObject есть параметр -AsJob, который запускает командлет в фоне, но там нельзя выбрать произвольное имя задачи. | ||
+ | <code powershell> | ||
+ | get-wmiobject win32_operatingsystem -computername (get-content allservers.txt) –asjob | ||
+ | |||
+ | WARNING: column " | ||
+ | Id Name State HasMoreData Location | ||
+ | -- ---- ----- ----------- -------- | ||
+ | 5 Job5 Running False server-r2, | ||
+ | |||
+ | # Посмотреть другие команды, | ||
+ | Help * -parameter asjob | ||
+ | </ | ||
+ | У Get-CimInstance нет параметра -AsJob, его нужно использовать в сочетании с Start-Job или Invoke-Command. | ||
+ | |||
+ | Создание удалённой фоновой задачи: | ||
+ | <code powershell> | ||
+ | invoke-command -command { get-process } | ||
+ | -computername (get-content .\allservers.txt ) | ||
+ | -asjob -jobname MyRemoteJob | ||
+ | |||
+ | WARNING: column " | ||
+ | Id Name State HasMoreData Location | ||
+ | -- ---- ----- ----------- -------- | ||
+ | 8 MyRemoteJob Running True server-r2, | ||
+ | </ | ||
+ | |||
+ | Просмотр результатов | ||
+ | <code powershell> | ||
+ | get-job # список задач | ||
+ | get-job -id 1 | fl * # подробности первой задачи | ||
+ | receive-job -id 1 # вывод результатов. Нужно указать ID или имя задачи | ||
+ | # сортировка результата удалённой задачи | ||
+ | receive-job -name myremotejob | sort-object PSComputerName | | ||
+ | Format-Table -groupby PSComputerName | ||
+ | </ | ||
+ | * Если вывести результаты материнской задачи, | ||
+ | * Обычно после получения результатов кэш стирается, | ||
+ | * Результаты могут не быть объектами (deserialized objects), и методы к ним не могут применяться, | ||
+ | |||
+ | Контекст запуска задачи и команд в этой задаче различается, | ||
+ | <code powershell> | ||
+ | C:\> start-job -scriptblock { dir } | ||
+ | # выведет список по пути | ||
+ | $env: | ||
+ | </ | ||
+ | Поэтому, | ||
+ | |||
+ | Работа с задачами | ||
+ | * Remove-Job - удалить вместе с результатом выполнения в кэше | ||
+ | * Stop-Job - прервать выполнение, | ||
+ | * Wait-Job - полезно в скрипте, | ||
+ | |||
+ | <code powershell> | ||
+ | # Показать дочерние задания | ||
+ | get-job -id 1 | select -expand childjobs | ||
+ | # грохнуть все задачи, | ||
+ | get-job | where { -not $_.HasMoreData } | remove-job | ||
+ | </ | ||
+ | Если фоновая задача выполнилась с ошибкой (State failed), то текст ошибки хранится как результат в дочерней задаче. | ||
+ | |||
+ | === Запланированные задачи (scheduled jobs) === | ||
+ | Это несколько отличается как от фоновых задач PS, так и от заданий в планировщике Windows (scheduled tasks). Чтобы создать задачу, | ||
+ | <code powershell> | ||
+ | Register-ScheduledJob -Name DailyProcList -ScriptBlock { | ||
+ | Get-Process } -Trigger (New-JobTrigger -Daily -At 2am) | ||
+ | -ScheduledJobOption (New-ScheduledJobOption -WakeToRun -RunElevated) | ||
+ | </ | ||
+ | Если запросить список задач (Get-Job), то видно, что каждый раз при выполнении запланированной задачи создаётся задача в списке, | ||
+ | |||
+ | Как делать не надо: | ||
+ | <code powershell> | ||
+ | # после запуска соединение прерывается, | ||
+ | invoke-command -command { Start-Job -scriptblock { dir } } -computername Server-R2 | ||
+ | # здесь нужно использовать -AsJob у Invoke-Command | ||
+ | start-job -scriptblock { invoke-command -command { dir } -computername SERVER-R2 } | ||
+ | </ | ||
+ | Вообще, | ||
+ | |||
+ | Задачи существуют, | ||
+ | <code powershell> | ||
+ | # Последние 25 ошибок из системного лога выгружать в XML | ||
+ | # с пн по пт в 6:00 | ||
+ | Register-ScheduledJob -ScriptBlock {Get-EventLog -LogName System -Newest 25 -EntryType Error | | ||
+ | Export-Clixml -Path C: | ||
+ | New-JobTrigger -Weekly -DaysOfWeek 1,2,3,4,5 -At 6AM) | ||
+ | </ | ||
+ | |||
+ | ==== Работа со многими объектами одновременно ==== | ||
+ | В отличие от подхода, | ||
+ | |||
+ | Предпочтительный путь - использование " | ||
+ | <code powershell> | ||
+ | Get-Service | Stop-Service | ||
+ | Get-Service -name BITS, | ||
+ | |||
+ | # Недостаток - не видно вывода от предыдущих команд | ||
+ | Get-Service -name BITS, | ||
+ | # Теперь видно, с использованием -PassThru | ||
+ | Get-Service -name BITS -computer Server1, | ||
+ | </ | ||
+ | |||
+ | Другой способ - вызов метода. Положим, | ||
+ | <code powershell> | ||
+ | # Запрос интеловских адаптеров | ||
+ | gwmi win32_networkadapterconfiguration -filter " | ||
+ | # Вывод доступных объектов внутри, | ||
+ | gwmi win32_networkadapterconfiguration -filter " | ||
+ | # Вот так работать не будет: | ||
+ | gwmi win32_networkadapterconfiguration -filter " | ||
+ | # Нужно использовать специальную команду для вызова методов WMI | ||
+ | # Код возврата выполненного метода (ReturnValue) можно погуглить | ||
+ | gwmi win32_networkadapterconfiguration -filter " | ||
+ | # То же самое с CIM | ||
+ | gcim -classname win32_networkadapterconfiguration -filter " | ||
+ | </ | ||
+ | Также, можно в случае с WMI/CIM поискать другой, | ||
+ | |||
+ | Тем не менее, иногда приходится использовать перебор. Например, | ||
+ | <code powershell> | ||
+ | # Так работать не будет: | ||
+ | gwmi win32_service -filter "name = ' | ||
+ | change -arg $null, | ||
+ | # Invoke-WmiMethod : Input string was not in a correct format. | ||
+ | |||
+ | # Можно долго выяснять, | ||
+ | gwmi win32_service -filter "name = ' | ||
+ | % {$_.change($null, | ||
+ | </ | ||
+ | |||
+ | Иллюстрация разных подходов | ||
+ | <code powershell> | ||
+ | Get-Service -name *B* | Stop-Service # пакетная команда | ||
+ | Get-Service -name *B* | % { $_.Stop()} # перебор | ||
+ | Get-WmiObject Win32_Service -filter "name LIKE ' | ||
+ | Invoke-WmiMethod -name StopService # WMI | ||
+ | Get-WmiObject Win32_Service -filter "name LIKE ' | ||
+ | % { $_.StopService()} # WMI с перебором | ||
+ | Stop-Service -name *B* # специализированная команда | ||
+ | </ | ||
+ | Нельзя передать что-либо методу через пайп, передать можно только другой команде. Если команда не умеет делать то, что нужно, а метод умеет, тогда используется foreach и дальше вызывается нужный метод. | ||
+ | <code powershell> | ||
+ | Get-Something | ForEach-Object { $_.Delete() } | ||
+ | </ | ||
+ | |||
+ | ==== Безопасность ==== | ||
+ | Политика выполнения скриптов - в клиентских системах вообще запрещено (Restricted), | ||
+ | Можно управлять политикой выполнения через GPO (Computer Configuration -> Policies -> Administrative Templates -> Windows Components -> Windows PowerShell). | ||
+ | AllSigned - все скрипты должны быть подписаны доверенным УЦ.\\ | ||
+ | Unrestricted - можно всё.\\ | ||
+ | Bypass - для использования в приложениях, | ||
+ | |||
+ | <WRAP round tip 80%> | ||
+ | Plenty of experts, including Microsoft’s own “Scripting Guy,” suggest | ||
+ | using the Unrestricted setting for ExecutionPolicy. Their feeling is that the | ||
+ | feature doesn’t provide a layer of security, and you shouldn’t give yourself | ||
+ | false confidence that it’s protecting you from anything. | ||
+ | </ | ||
+ | |||
+ | Дополнительные меры: | ||
+ | - Скрипты .ps1 не выполняются по двойному клику мышкой, | ||
+ | - Запустить скрипт из консоли невозможно, | ||
+ | |||
+ | Сделать самоподписанный сертификат для подписи кода | ||
+ | <code powershell> | ||
+ | help about_signing | ||
+ | New-SelfSignedCertificate | ||
+ | </ | ||
+ | |||
+ | ==== Переменные - место для хранения ==== | ||
+ | Переменные могут содержать пробелы, | ||
+ | <code powershell> | ||
+ | $var = 'What does $var contain?' | ||
+ | $var | ||
+ | What does $var contain? | ||
+ | |||
+ | $computername = ' | ||
+ | $phrase = "The computer name is $computername" | ||
+ | $phrase | ||
+ | The computer name is SERVER-R2 | ||
+ | </ | ||
+ | |||
+ | Символ ` (escape character, под ~) - отменяет действие последующего символа, | ||
+ | <code powershell> | ||
+ | $computername = ' | ||
+ | $phrase = " | ||
+ | $phrase | ||
+ | $computername contains SERVER-R2 | ||
+ | |||
+ | $phrase = " | ||
+ | $phrase | ||
+ | $computername | ||
+ | contains | ||
+ | SERVER-R2 | ||
+ | |||
+ | # справка | ||
+ | help about_escape | ||
+ | </ | ||
+ | <code powershell> | ||
+ | # Несколько объектов в переменной | ||
+ | $computers = ' | ||
+ | $computers | ||
+ | SERVER-R2 | ||
+ | SERVER1 | ||
+ | Localhost | ||
+ | |||
+ | # Извлечение отдельных элементов из массива | ||
+ | # Первый объект - 0, второй - 1, последний - -1, предпоследний - -2 | ||
+ | $computers[0] | ||
+ | SERVER-R2 | ||
+ | $computers[1] | ||
+ | SERVER1 | ||
+ | $computers[-1] | ||
+ | localhost | ||
+ | $computers[-2] | ||
+ | SERVER1 | ||
+ | |||
+ | # Подсчёт кол-ва объектов | ||
+ | $computers.count | ||
+ | 3 | ||
+ | |||
+ | # Вызов свойств и методов | ||
+ | $computername.length | ||
+ | 9 | ||
+ | $computername.toupper() | ||
+ | SERVER-R2 | ||
+ | $computername.tolower() | ||
+ | server-r2 | ||
+ | $computername.replace(' | ||
+ | SERVER-2008 | ||
+ | $computername | ||
+ | SERVER-R2 | ||
+ | |||
+ | # Применительно к отдельному объекту массива | ||
+ | $computers[0].tolower() | ||
+ | server-r2 | ||
+ | $computers[1].replace(' | ||
+ | CLIENT1 | ||
+ | |||
+ | # Заменить значение в массиве | ||
+ | $computers[1] = $computers[1].replace(' | ||
+ | $computers | ||
+ | SERVER-R2 | ||
+ | CLIENT1 | ||
+ | Localhost | ||
+ | |||
+ | # Обработка всех значений в массиве | ||
+ | $computers = $computers | ForEach-Object { $_.ToLower()} | ||
+ | $computers | ||
+ | server-r2 | ||
+ | client1 | ||
+ | localhost | ||
+ | </ | ||
+ | |||
+ | В PS v1 и v2 у переменных, | ||
+ | <code powershell> | ||
+ | # PS v3 понимает, | ||
+ | $services = Get-Service | ||
+ | $services.Name | ||
+ | # Для предыдущих версий нужно было бы делать так | ||
+ | Get-Service | ForEach-Object { Write-Output $_.Name } | ||
+ | # или так | ||
+ | Get-Service | Select-Object –ExpandProperty Name | ||
+ | |||
+ | # то же работает и для методов | ||
+ | $objects = Get-WmiObject –class Win32_Service –filter " | ||
+ | $objects.ChangeStartMode(' | ||
+ | </ | ||
+ | |||
+ | <code powershell> | ||
+ | # Так работать не будет - двойные кавычки не воспринимают | ||
+ | # конструкцию [0].name как функциональную часть | ||
+ | $services = get-service | ||
+ | $firstname = " | ||
+ | $firstname | ||
+ | AeLookupSvc ALG AllUserInstallAgent AppIDSvc ... wudfsvc WwanSvc[0].name | ||
+ | # без кавычек это будет работать | ||
+ | |||
+ | # если кавычки всё же нужны, то используется субпеременная $() | ||
+ | $services = get-service | ||
+ | $firstname = "The first name is $($services[0].name)" | ||
+ | $firstname | ||
+ | The first name is AeLookupSvc | ||
+ | </ | ||
+ | |||
+ | Иногда принудительное указание типа переменной необходимо. | ||
+ | <code powershell> | ||
+ | $number = Read-Host "Enter a number" | ||
+ | Enter a number: 100 | ||
+ | $number = $number * 10 | ||
+ | $number | ||
+ | 100100100100100100100100100100 | ||
+ | # в данном случае 100 воспринимается как строка, | ||
+ | # и повторяется 10 раз вместо умножения. | ||
+ | # Посмотреть тип переменной: | ||
+ | $number |gm | ||
+ | |||
+ | # надо указать переменную так: | ||
+ | [int]$number = Read-Host "Enter a number" | ||
+ | </ | ||
+ | Популярные типы переменных: | ||
+ | * [int] - целое число | ||
+ | * [single] и [double] - число с одним или двумя знаками после разделителя | ||
+ | * [string] - строка | ||
+ | * [char] - один символ | ||
+ | * [xml] - документ с разметкой XML | ||
+ | * [adsi] - запрос Active Directory Service Interfaces | ||
+ | |||
+ | ==== Ввод и вывод ==== | ||
+ | Запрос информации от пользователя | ||
+ | <code powershell> | ||
+ | $computername = read-host "Enter a computer name" | ||
+ | Enter a computer name: SERVER-R2 | ||
+ | </ | ||
+ | Чтобы создать при запросе графическое окно, нужно использовать .NET | ||
+ | <code powershell> | ||
+ | # the void data type is a special type that means “throw the result away.” | ||
+ | # Another way to do the same thing would be to pipe the result to Out-Null. | ||
+ | [void][System.Reflection.Assembly]:: | ||
+ | # 1 - текст запроса, | ||
+ | $computername = [Microsoft.VisualBasic.Interaction]:: | ||
+ | </ | ||
+ | Вывод | ||
+ | <code powershell> | ||
+ | write-host " | ||
+ | </ | ||
+ | Write-Host используется только для показа информации, | ||
+ | |||
+ | В отличие от Write-Host, Write-Output умеет передавать информацию через пайп и технически не предназначена для отображения. | ||
+ | <code powershell> | ||
+ | # Если написать | ||
+ | write-output " | ||
+ | # то информация пройдёт путь write-output " | ||
+ | |||
+ | # ничего не выведется | ||
+ | write-output " | ||
+ | # Hello будет выведено, | ||
+ | write-host " | ||
+ | </ | ||
+ | |||
+ | Другие команды вывода, | ||
+ | ^ Cmdlet ^ Purpose ^ Configuration variable ^ | ||
+ | | Write-Warning | Displays warning text, in yellow by default, and preceded by the label WARNING: | $WarningPreference (Continue by default) | | ||
+ | | Write-Verbose | Displays additional informative text, in yellow by default, and preceded by the label VERBOSE: | $VerbosePreference (SilentlyContinue by default) | | ||
+ | | Write-Debug | Displays debugging text, in yellow by default, and preceded by the label DEBUG: | $DebugPreference (SilentlyContinue by default) | | ||
+ | | Write-Error | Produces an error message (работает немного по-другому, | ||
+ | |||
+ | Есть ещё Write-Progress, | ||
+ | |||
+ | ==== Сессии: | ||
+ | В отличие от рассматривавшихся ранее Invoke-Command и Enter-PSSession, | ||
+ | |||
+ | Используя New-PSSession, | ||
+ | <code powershell> | ||
+ | new-pssession -computername server-r2, | ||
+ | # вызвать сессии | ||
+ | get-pssession | ||
+ | # удобно помещать в переменную | ||
+ | $iis_servers = new-pssession -comp web1, | ||
+ | # закрыть | ||
+ | $iis_servers | remove-pssession | ||
+ | # закрыть все (при закрытии консоли сессии закрываются автоматически) | ||
+ | get-pssession | remove-pssession | ||
+ | # зайти на первый сервер | ||
+ | enter-pssession -session $iis_servers [0] | ||
+ | # или так, если порядок неизвестен | ||
+ | enter-pssession -session ($iis_servers |where { $_.computername -eq ' | ||
+ | # или так (PS хранит сессии в общем списке, | ||
+ | enter-pssession -session (get-pssession -computer web1) | ||
+ | Get-PSSession -ComputerName web1 | Enter-PSSession # как вариант | ||
+ | # выйти | ||
+ | exit-pssession | ||
+ | </ | ||
+ | Записывать сессии в переменную имеет смысл только тогда, когда компьютеров несколько. | ||
+ | |||
+ | <code powershell> | ||
+ | $serv = New-PSSession -ComputerName serv1, | ||
+ | Invoke-Command -Command {gwmi win32_process |select processname, | ||
+ | </ | ||
+ | У Get-WmiObject есть свой параметр -computername (у Get-CimInstance нет, он заточен под использование удалённых сессий), | ||
+ | * Удалённый доступ PS использует определённый порт, WMI нет. | ||
+ | * Удалённый доступ экономит ресурсы, | ||
+ | * Удалённые запросы выполняются параллельно, | ||
+ | * Ранее заданные сессии не могут быть использованы с Get-WmiObject | ||
+ | |||
+ | <code powershell> | ||
+ | # Параметры -session можно дать результат команды в скобках. | ||
+ | Invoke-Command -Command {gwmi win32_process |select processname, | ||
+ | # В данном случае, | ||
+ | </ | ||
+ | |||
+ | Неявный доступ (implicit remoting) - импорт модулей и оснасток с удалённой машины. Удобно в случаях, | ||
+ | <code powershell> | ||
+ | # установка соединения | ||
+ | $session = new-pssession -comp server-r2 | ||
+ | # Загрузка нужного модуля | ||
+ | invoke-command -command { import-module activedirectory } -session $session | ||
+ | # Импорт команд модуля с добавлением префикса rem, чтобы не было путаницы (New-remADUser) | ||
+ | import-pssession -session $session -module activedirectory -prefix rem | ||
+ | # создаётся временный локальный модуль | ||
+ | </ | ||
+ | Команды выполняются на удалённой машине и будут доступны до закрытия сессии или окна терминала. Минус - результат выполнения команд не будет объектами (deserialized). | ||
+ | |||
+ | С PSv3 можно возобновлять закрытые сессии | ||
+ | <code powershell> | ||
+ | # Id Name ComputerName State | ||
+ | # 4 Session4 COMPUTER2 Disconnected | ||
+ | Get-PSSession -computerName COMPUTER2 | Connect-PSSession | ||
+ | </ | ||
+ | Управлять параметрами сессий можно через GPO или WSMan drive (WSMan: | ||
+ | ==== Скриптинг ==== | ||
+ | С параметрами и документацией | ||
+ | <file powershell Get-DiskInventory.ps1> | ||
+ | <# | ||
+ | .SYNOPSIS | ||
+ | Get-DiskInventory retrieves logical disk information from one or | ||
+ | more computers. | ||
+ | .DESCRIPTION | ||
+ | Get-DiskInventory uses WMI to retrieve the Win32_LogicalDisk | ||
+ | instances from one or more computers. It displays each disk's | ||
+ | drive letter, free space, total size, and percentage of free | ||
+ | space. | ||
+ | .PARAMETER computername | ||
+ | The computer name, or names, to query. Default: Localhost. | ||
+ | .PARAMETER drivetype | ||
+ | The drive type to query. See Win32_LogicalDisk documentation | ||
+ | for values. 3 is a fixed disk, and is the default. | ||
+ | .EXAMPLE | ||
+ | Get-DiskInventory -computername SERVER-R2 -drivetype 3 | ||
+ | #> | ||
+ | param ( | ||
+ | $computername = ' | ||
+ | $drivetype = 3 | ||
+ | ) | ||
+ | gwmi Win32_LogicalDisk -comp $computername -filter " | ||
+ | Sort DeviceID | | ||
+ | ft DeviceID, | ||
+ | @{n=' | ||
+ | @{n=' | ||
+ | </ | ||
+ | Значения параметров - значения по умолчанию. | ||
+ | <code powershell> | ||
+ | # Справка | ||
+ | help .\Get-DiskInventory -full | ||
+ | # почитать про справку | ||
+ | help about_comment_based_help | ||
+ | </ | ||
+ | |||
+ | Скрипт выполняется в одном потоке, | ||
+ | |||
+ | Область (scope) - форма контейнера для хранения элементов PS. Сама консоль - global scope, верхний уровень. При запуске скрипта образуется script scope, являющийся дочерним (child) к global scope (parent). У функций есть свои private scopes, дочерние к скрипту. Все области существуют, | ||
+ | ==== Совершенствование задания параметров в скриптах ==== | ||
+ | Сделать параметр Computername обязательным, | ||
+ | |||
+ | Добавлен более подробный вывод процесса выполнения в консоль с помощью Write-Verbose - для того, чтобы эти сообщения показывались, | ||
+ | <code powershell> | ||
+ | [CmdletBinding()] | ||
+ | param ( | ||
+ | [Parameter(Mandatory=$True, | ||
+ | [Alias(' | ||
+ | [string]$computername, | ||
+ | [ValidateSet(2, | ||
+ | [int]$drivetype = 3 | ||
+ | ) | ||
+ | Write-Verbose " | ||
+ | Write-Verbose " | ||
+ | gwmi Win32_LogicalDisk -comp $computername -filter " | ||
+ | Sort DeviceID | | ||
+ | ft DeviceID, | ||
+ | @{n=' | ||
+ | @{n=' | ||
+ | Write-Verbose " | ||
+ | </ | ||
+ | * Все параметры заключены в блок param() | ||
+ | * Один параметр может иметь несколько декораторов (decorators), | ||
+ | * Имена параметров разделяются запятыми, | ||
+ | * Между параметрами лучше оставлять пустую строку, | ||
+ | * Параметры задаются как переменные, | ||
+ | <code powershell> | ||
+ | # Прочесть про опции параметров: | ||
+ | help about_functions_advanced_parameters | ||
+ | </ | ||
+ | Ещё пример | ||
+ | <code powershell> | ||
+ | [CmdletBinding()] | ||
+ | param( | ||
+ | [Parameter(Mandatory=$True)] | ||
+ | [Alias(' | ||
+ | $computername | ||
+ | ) | ||
+ | Write-Verbose " | ||
+ | gwmi win32_networkadapter -computername $computername | | ||
+ | where { $_.PhysicalAdapter } | | ||
+ | select MACAddress, | ||
+ | Write-Verbose " | ||
+ | </ | ||
+ | |||
+ | ==== Углублённая настройка удалённого управления ==== | ||
+ | Иногда нужно указывать битность при использовании, | ||
+ | <code powershell> | ||
+ | # Список доступных конфигураций | ||
+ | Get-PSSessionConfiguration | ||
+ | # Подключение с указанием конфигурации | ||
+ | Enter-PSSession -ComputerName DONJONES1D96 -ConfigurationName ' | ||
+ | </ | ||
+ | |||
+ | Создание конфигурации: | ||
+ | |||
+ | Это можно делать, | ||
+ | <code powershell> | ||
+ | New-PSSessionConfigurationFile -Path C: | ||
+ | -SessionType RestrictedRemoteServer -CompanyName "Our Company" | ||
+ | | ||
+ | # -SessionType RestrictedRemoteServer - удаляет все базовые команды PS для этой сессии, | ||
+ | |||
+ | # Запуск конфигурации, | ||
+ | # -ShowSecurityDescriptorUI выводит окно с запросом, | ||
+ | Register-PSSessionConfiguration -Path .\HelpDeskEndpoint.pssc ` | ||
+ | -RunAsCredential COMPANY\HelpDeskProxyAdmin -ShowSecurityDescriptorUI ` | ||
+ | -Name HelpDesk | ||
+ | |||
+ | # Использование созданной конфигурации | ||
+ | Enter-PSSession -ComputerName DONJONES1D96 -ConfigurationName HelpDesk | ||
+ | # Список доступных команд | ||
+ | Get-Command | ||
+ | </ | ||
+ | |||
+ | Многоступенчатый удалённый доступ (multihop remoting). Если попробовать создать сессию на 3-й компьютер с удалённого, | ||
+ | <code powershell> | ||
+ | # На локальной машине (x - удалённый комп) | ||
+ | Enable-WSManCredSSP -Role Client -DelegateComputer x | ||
+ | # На удалённой машине | ||
+ | Enable-WSManCredSSP -Role Server | ||
+ | </ | ||
+ | |||
+ | При удалённом доступе PS проверяет подлинность в том числе удалённой машины для защиты от спуфинга. Если указывается IP-адрес или алиас, то стандартный метод проверки не работает - надо задействовать SSL или TrustedHosts. См. бесплатную книгу //Secrets of PowerShell Remoting// для более подробной информации. | ||
+ | ==== Регулярные выражения (regex) для разбора текстовых файлов ==== | ||
+ | В данном случае, | ||
+ | |||
+ | В PS слово уже является regex, т. к. запросы нечувствительны к регистру, | ||
+ | * \w - буква, цифра или подчёркивание, | ||
+ | * \W - наоборот | ||
+ | * \d - цифра | ||
+ | * \D - не цифра | ||
+ | * \s - любой " | ||
+ | * \S - не \s | ||
+ | * . - один символ | ||
+ | * [abcde] - набор символов для сравнения, | ||
+ | * [a-z] - диапазон символов для сравнения, | ||
+ | * [^abcde] - набор символов НЕ для сравнения, | ||
+ | * ? - обозначает один экземпляр предыдущего символа или его отсутствие. do?n = don, donn или dn, но не doon. | ||
+ | * * - любое кол-во символов | ||
+ | * + - любое кол-во предыдущего символа или группы символов: | ||
+ | * \ - экранирующий символ, | ||
+ | * {2} - кол-во предыдущих символов. \d{1} - одна цифра, {2,} - два символа и более, {1,3} - от одного до трёх. | ||
+ | * ^ - начало строки. ^d.n = donrrr, но не равно rrrdon | ||
+ | * $ - конец строки. | ||
+ | |||
+ | <code powershell> | ||
+ | # справка | ||
+ | help about_regular_expressions | ||
+ | |||
+ | # примеры | ||
+ | " | ||
+ | True | ||
+ | " | ||
+ | False | ||
+ | " | ||
+ | True | ||
+ | " | ||
+ | False | ||
+ | " | ||
+ | False | ||
+ | " | ||
+ | True | ||
+ | # 6\.2; — This is 6.2; and notice that we escaped the period to make it a literal character | ||
+ | # rather than the single-character wildcard that a period normally indicates. | ||
+ | # [\w\W]+ — This is one or more word or nonword characters—in other words, anything. | ||
+ | # \+Gecko — This is a literal +, then Gecko. | ||
+ | |||
+ | C: | ||
+ | select-string -pattern " | ||
+ | ft Filename, | ||
+ | |||
+ | # имена с двумя цифрами | ||
+ | dir $env:windir |? Name -match " | ||
+ | |||
+ | # выбрать из кэша записи с IP-адресами | ||
+ | Get-DNSClientCache |? Data -match " | ||
+ | |||
+ | </ | ||
+ | |||
+ | [[https:// | ||
+ | ==== Разные прочие техники и трюки ==== | ||
+ | Можно задать профиль для PS - настройки при каждом запуске, | ||
+ | <code powershell> | ||
+ | Import-Module ActiveDirectory | ||
+ | Add-PSSnapin SqlServerCmdletSnapin100 | ||
+ | cd c:\ | ||
+ | |||
+ | # справка по профилям | ||
+ | help about_profiles | ||
+ | </ | ||
+ | Профиль относится к приложению PS (hosting application - консоль, | ||
+ | - $pshome\profile.ps1 - для всех пользователей и всех приложений | ||
+ | - $pshome\Microsoft.PowerShell_profile.ps1 - для консоли, | ||
+ | - $home\Documents\WindowsPowerShell\profile.ps1 - для данного пользователя и всех приложений | ||
+ | - $home\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 - консоль, | ||
+ | |||
+ | " | ||
+ | |||
+ | === Операторы === | ||
+ | <code powershell> | ||
+ | # -as - создание объекта с другим типом | ||
+ | 1000 / 3 -as [int] | ||
+ | # -is - проверяет объект и возвращает True или False | ||
+ | 123.45 -is [int] # false | ||
+ | " | ||
+ | $True -is [bool] # true | ||
+ | (Get-Date) -is [datetime] # true | ||
+ | # -replace | ||
+ | " | ||
+ | 192.168.15.12 | ||
+ | # -join | ||
+ | $array = " | ||
+ | PS C:\> $array | ||
+ | one | ||
+ | two | ||
+ | three | ||
+ | four | ||
+ | five | ||
+ | $array -join " | ||
+ | one|two|three|four|five | ||
+ | # -split | ||
+ | (gc computers.tdf) -split " | ||
+ | Server1 | ||
+ | Windows | ||
+ | East | ||
+ | Managed | ||
+ | $array[0] | ||
+ | Server1 | ||
+ | # -contains | ||
+ | ' | ||
+ | False | ||
+ | ' | ||
+ | True | ||
+ | |||
+ | $collection = ' | ||
+ | $collection -contains ' | ||
+ | True | ||
+ | $collection -contains ' | ||
+ | False | ||
+ | |||
+ | # -in - возвращает true or false | ||
+ | $collection = ' | ||
+ | ' | ||
+ | True | ||
+ | ' | ||
+ | False | ||
+ | </ | ||
+ | |||
+ | === Манипуляции со строками === | ||
+ | <code powershell> | ||
+ | " | ||
+ | |||
+ | # метод IndexOf() | ||
+ | " | ||
+ | 6 | ||
+ | |||
+ | # Split(), Join(), and Replace() operate similarly to the -split, -join, and -replace operators | ||
+ | # ToLower() and ToUpper() | ||
+ | " | ||
+ | hello | ||
+ | # trim () | ||
+ | " | ||
+ | HeLLo | ||
+ | |||
+ | |||
+ | |||
+ | </ | ||
+ | |||
+ | === Манипуляции с датой === | ||
+ | <code powershell> | ||
+ | get-date | gm | ||
+ | (get-date).month | ||
+ | (get-date).adddays(-90) | ||
+ | (get-date).ToShortDateString() | ||
+ | 28.05.2019 | ||
+ | </ | ||
+ | |||
+ | === Даты WMI === | ||
+ | <code powershell> | ||
+ | # У WMI нечеловеческий формат дат | ||
+ | get-wmiobject win32_operatingsystem | select lastbootuptime | ||
+ | lastbootuptime | ||
+ | -------------- | ||
+ | 20190528095517.490356+180 | ||
+ | |||
+ | get-wmiobject win32_operatingsystem |gm | ||
+ | # есть методы converttodatetime и convertfromdatetime | ||
+ | $i = get-wmiobject win32_operatingsystem | ||
+ | $i.converttodatetime($i.lastbootuptime) | ||
+ | 28 мая 2019 г. 9:55:17 | ||
+ | |||
+ | get-wmiobject win32_operatingsystem | select BuildNumber, | ||
+ | @{l=' | ||
+ | |||
+ | # Команды CIM сразу выдают нормальный формат | ||
+ | gcim win32_operatingsystem | select lastbootuptime | ||
+ | lastbootuptime | ||
+ | -------------- | ||
+ | 28.05.2019 9:55:17 | ||
+ | </ | ||
+ | |||
+ | === Задание стандартных значений параметров === | ||
+ | Например, | ||
+ | Умолчания хранятся в спец. переменной // | ||
+ | |||
+ | Положим, | ||
+ | <code powershell> | ||
+ | $credential = Get-Credential -UserName Administrator -Message "Enter Admin credential" | ||
+ | $PSDefaultParameterValues.Add(' | ||
+ | # сделать это только для Invoke-Command | ||
+ | $PSDefaultParameterValues.Add(' | ||
+ | {Get-Credential -Message 'Enter administrator credential' | ||
+ | # используется метод add()? 1-й аргумент - команда, | ||
+ | # посмотреть список стандартных параметров | ||
+ | $PSDefaultParameterValues | ||
+ | # справка | ||
+ | help about_parameters_default_values | ||
+ | </ | ||
+ | $PSDefaultParameterValues, | ||
+ | |||
+ | === Scriptblocks === | ||
+ | Скриптблок - то, что заключено в {}, кроме хэш-таблиц @{} | ||
+ | * where -filterscript даёт скриптблок | ||
+ | * foreach -process даёт скриптблок | ||
+ | * Хэш-таблицы, | ||
+ | * Некоторые команды принимают скриптблоки в качестве параметра: | ||
+ | |||
+ | Чтобы вызвать скриптблок, | ||
+ | <code powershell> | ||
+ | $block = {get-process | sort -Property vm -Descending | select -first 10} | ||
+ | &$block | ||
+ | # справка | ||
+ | help about_script_blocks | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | ==== Памятка ==== | ||
+ | При использовании чужих скриптов необходимо полностью понимать, | ||
+ | * Распознать переменные, | ||
+ | * Читать справку к новым командам | ||
+ | * Использовать тестовую среду, например, | ||
+ | |||
+ | === Пунктуация === | ||
+ | ` (обратная кавычка) - экранирует последующий символ. Например, | ||
+ | <code powershell> | ||
+ | cd c:\Program` Files | ||
+ | </ | ||
+ | ~ - папка профиля | ||
+ | |||
+ | ( ) - как в арифметике, | ||
+ | <code powershell> | ||
+ | Get-Service -computerName (Get-Content c: | ||
+ | </ | ||
+ | Если скобки - это параметры метода, | ||
+ | |||
+ | [ ] - индекс объекта в массиве, | ||
+ | |||
+ | { } - скриптблок или фильтр | ||
+ | <code powershell> | ||
+ | Get-Service | Where-Object { $_.Status -eq ' | ||
+ | # ключ=значение в хэш-таблицах | ||
+ | $hashtable = @{l=' | ||
+ | # как вариант написания переменной с пробелами и другими нестандартными символами | ||
+ | ${My Variable} | ||
+ | </ | ||
+ | |||
+ | ' ' - буквальное прочтение содержимого, | ||
+ | |||
+ | %%" "%% - переменные, | ||
+ | <code powershell> | ||
+ | $two = "Hello $one `n" | ||
+ | </ | ||
+ | |||
+ | $ - знак переменной | ||
+ | |||
+ | % - foreach. It’s also the modulus operator, returning the remainder from a division operation. | ||
+ | |||
+ | ? - where | ||
+ | |||
+ | %%>%% - направление вывода (Out-File) | ||
+ | |||
+ | +, -, /, % - математические операторы. " | ||
+ | |||
+ | - - указывает на параметр или оператор (-computerName, | ||
+ | |||
+ | @ - указатель на: | ||
+ | - хэш-таблицу @{} | ||
+ | - массив $array = @(1,2,3,4). можно обойтись просто 1,2,3,4, т.к. PS и так воспринимает список с разделителями-запятыми как массив. | ||
+ | - here-string - %%@" "@%% - блок с буквально читаемой строкой, | ||
+ | - [[https:// | ||
+ | |||
+ | & - вызов (invocation operator), типа call в CMD | ||
+ | |||
+ | ; - разделитель двух команд, | ||
+ | |||
+ | # - комментарий, | ||
+ | |||
+ | = - оператор присвоения. В сравнениях не используется, | ||
+ | |||
+ | | - передача потока данных от одной команде другой. | ||
+ | |||
+ | / или \ - прямой - это деление, | ||
+ | |||
+ | . - вызов метода или свойства ($_.Status), | ||
+ | |||
+ | , - вне кавычек - разделитель членов массива или значений для свойства команды (Get-Process -computername Server1, | ||
+ | |||
+ | : - (технически, | ||
+ | |||
+ | ! - то же, что -not | ||
+ | |||
+ | === В справке === | ||
+ | '' | ||
+ | |||
+ | %%< >%% - типы данных (< | ||
+ | |||
+ | === Операторы === | ||
+ | * -eq - равенство (-ceq - чувств. к регистру) | ||
+ | * -ne - неравенство (-cne - чувств. к регистру) | ||
+ | * -ge - больше или равно | ||
+ | * -le - меньше или равно | ||
+ | * -gt - больше, | ||
+ | * -lt - меньше, | ||
+ | * -contains - содержит объект ($collection -contains $object), возврат true or false, -notcontains - наоборот | ||
+ | * -in - объект содержится в ($object -in $collection), | ||
+ | |||
+ | Логические: | ||
+ | * -not (или !) - true or false | ||
+ | * -and - и | ||
+ | * -or - или | ||
+ | |||
+ | Функциональные: | ||
+ | * -join - объединяет строки в массив | ||
+ | * -split - разъединяет массив в строки | ||
+ | * -replace - замена одной строки на другую | ||
+ | * -is - true, если объект такого типа ($one -is [int]) | ||
+ | * -as - назначение типа объекта ($one -as [int]) | ||
+ | * .. - диапазон (1..10) | ||
+ | * -f - format operator, замена значений в массиве %%" | ||
+ | |||
+ | Передача параметров через пайп делается двумя способами: | ||
+ | |||
+ | $_ используется в скриптблоках после пайпа | ||
+ | <code powershell> | ||
+ | Get-Service |? {$_.Status -eq ' | ||
+ | gwmi -class Win32_Service -filter " | ||
+ | foreach -process { $_.ChangeStartMode(' | ||
+ | </ | ||
+ | В любом случае, | ||
+ | |||
+ | ===== PowerShell in Depth ===== | ||
+ | ==== Custom Object ==== | ||
+ | Вариант 1: | ||
+ | <code powershell> | ||
+ | $os = Get-WmiObject –Class Win32_OperatingSystem –comp localhost | ||
+ | $cs = Get-WmiObject –Class Win32_ComputerSystem –comp localhost | ||
+ | $bios = Get-WmiObject –Class Win32_BIOS –comp localhost | ||
+ | $proc = Get-WmiObject –Class Win32_Processor –comp localhost | | ||
+ | Select –First 1 | ||
+ | $props = @{OSVersion=$os.version | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | $obj = New-Object –TypeName PSObject –Property $props | ||
+ | Write-Output $obj | ||
+ | </ | ||
+ | |||
+ | В PS v3 и новее можно задать порядок свойств: | ||
+ | <code powershell> | ||
+ | $props = [ordered]@{ OSVersion=$os.version | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | Вариант 2 (не рекомендуется, | ||
+ | <code powershell> | ||
+ | $obj = "" | ||
+ | | ||
+ | $obj.ComputerName = $os.CSName | ||
+ | $obj.OSVersion = $os.version | ||
+ | $obj.OSArchitecture = $os.osarchitecture | ||
+ | $obj.ProcArchitecture = $proc.addresswidth | ||
+ | $obj.BIOSSerial = $bios.serialnumber | ||
+ | $obj.Model = $cs.model | ||
+ | $obj.Manufacturer = $cs.manufacturer | ||
+ | </ | ||
+ | |||
+ | Вариант 3: | ||
+ | <code powershell> | ||
+ | $obj = New-Object –TypeName PSObject | ||
+ | $obj | Add-Member NoteProperty ComputerName $os.CSName | ||
+ | $obj | Add-Member NoteProperty OSVersion $os.version | ||
+ | $obj | Add-Member NoteProperty OSArchitecture $os.osarchitecture | ||
+ | $obj | Add-Member NoteProperty ProcArchitecture $proc.addresswidth | ||
+ | $obj | Add-Member NoteProperty BIOSSerial $bios.serialnumber | ||
+ | $obj | Add-Member NoteProperty Model $cs.model | ||
+ | $obj | Add-Member NoteProperty Manufacturer $cs.manufacturer | ||
+ | </ | ||
+ | |||
+ | или так: | ||
+ | <code powershell> | ||
+ | $obj | Add-Member NoteProperty ComputerName $os.CSName –pass | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | Вариант 4 (для PS v3 или новее): | ||
+ | <code powershell> | ||
+ | $obj = [pscustomobject]@{OSVersion=$os.version | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | Свойства получаются сразу упорядоченными. | ||
+ | |||
+ | Вариант 5 - создать новый класс: | ||
+ | <code powershell> | ||
+ | $source=@" | ||
+ | public class MyObject | ||
+ | { | ||
+ | public string ComputerName {get; set;} | ||
+ | public string Model {get; set;} | ||
+ | public string Manufacturer {get; set;} | ||
+ | public string BIOSSerial {get; set;} | ||
+ | public string OSArchitecture {get; set;} | ||
+ | public string OSVersion {get; set;} | ||
+ | public string ProcArchitecture {get; set;} | ||
+ | } | ||
+ | "@ | ||
+ | Add-Type -TypeDefinition $source -Language CSharpversion3 | ||
+ | $os = Get-WmiObject –Class Win32_OperatingSystem –comp localhost | ||
+ | $cs = Get-WmiObject –Class Win32_ComputerSystem –comp localhost | ||
+ | $bios = Get-WmiObject –Class Win32_BIOS –comp localhost | ||
+ | $proc = Get-WmiObject –Class Win32_Processor –comp localhost | | ||
+ | Select –First 1 | ||
+ | $props = @{OSVersion=$os.version | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | $obj = New-Object –TypeName MyObject –Property $props | ||
+ | Write-Output $obj | ||
+ | </ | ||
+ | |||
+ | По быстродействию лучше всего варианты 4 и 1. | ||
+ | |||
+ | ===== Литература ===== | ||
+ | https:// | ||
+ | https:// | ||
+ | http:// | ||
+ | https:// | ||
+ | http:// | ||
+ | http:// | ||
+ | http:// | ||
+ | http:// | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | |||
+ | Книги: | ||
+ | Learn PowerShell Toolmaking in a Month of Lunches\\ | ||
+ | PowerShell in Depth | ||
+ | |||
+ | https:// | ||
+ | |||