PowerShell
Powershell - мова не чутлива до регістру. for, FOR, FoR, fOr
- йому все одно.
Командна оболонка
[ред.]Команди Powershell можна виконувати в своїй командній оболонці, подібній до cmd.exe, а можна в середовищі що називається Powershell ISE, і постачається разом з Powershell 2.0 та вище.
Коментарі
[ред.]В PowerShell, все в рядку що знаходиться справа від символу "дієз" буде вважатись коментарем.
це код # це коментар
# цей ввесь рядок - коментар
У версіях PowerShell більших за 2.0 (а це майже всі версії) можна використовувати блоковий коментар
це код <# а це - коментар #> і знову код.
<#
а тут взагалі
кожен рядок - коментар
#>
Командлети
[ред.]Команди Powershell називаються командлетами і складаються з двох частин розділених дефісом - дієслова та об’єкта. Наприклад командлет що дозволяє отримати список всіх доступних командлетів:
Get-Command -commandType cmdlet
Можна отримати інформацію про командлет використовуючи командлет Get-Help
[tn 1], після якого вказавши назву командлета. Get-Help Get-Command
дозволяє отримати всі розділи довідки.
Командлети мають параметри які дозволяють їм отримати додаткову інформацію про те що і як потрібно робити. Параметри бувають порядкові, іменовані та перемикачі.
Наприклад команда Get-ChildItem
[tn 2], яка перелічує дітей вузла якоїсь деревовидної структури (наприклад вміст каталогу файлової системи), має параметри:
-path
- іменований а також порядковий (перший) параметр що вказує чиїх дітей треба перелічити (наприкладGet-ChildItem C:\
.-recurse
- перемикач який дозволяє вказати командлету що треба також повернути дітей дітей.
Псевдоніми
[ред.]Якщо ви постійно працюєте в PowerShell, то щоразу набирати Get-ChildItem
буде дуже втомливо, тому для неї створені такі псевдоніми як ls
та dir
.
Список доступних псевдонімів можна отримати командою ls alias:
(отримати вміст віртуального диска alias
) або Get-Alias
.
Створити новий псевдонім можна за допомогою команди Set-Alias
, наприклад:
Set-Alias np notepad.exe
Видалити псевдонім np
:
Remove-Item alias:\np
Змінні
[ред.]Змінні, як і все інше в PowerShell нечутливі до регістру. Назва змінної може містити що завгодно, але якщо вона міститиме символи що можуть неоднозначно сприйнятись (наприклад прогалики) то її потрібно помістити в фігурні дужки. Кожна змінна позначається знаком долара ($) за яким йде її назва.
Змінні створюються при першому присвоєнні, наприклад:
$a = $b = 0 # присвоїти обом нуль
$a , $b = 2, 3 # $а буде 2, а $b - 3
Отримати список всіх наявних змінних можна за допомогою команди ls variable:
(отримати вміст віртуального диска variable
) або Get-Variable
.
Щоб перевірити існування змінної $a
можна так:
Test-Path variable:\a
Константи
[ред.]Окрім звичайного присвоєння, змінну можна створити за допомогою командлета New-Variable
, що дозволяє передати їй деякі додаткові параметри, наприклад вказати режим лише для читання:
New-Variable -Name pi -Value 3.1415926 -Option ReadOnly
Щоб видалити константу, доведеться передати в Remove-Item
ключ -Force
.
Змінні середовища
[ред.]Щоб отримати доступ до змінних середовища, використовують префікс env:
, наприклад $env:path
.
Щоправда кожен скрипт має свою копію набору змінних середовища, тому зміна їх значень призводить лише до змін всередині скрипта. Якщо ви захочете змінити змінну середовища на довший термін для користувача чи для всієї системи - використайте фукнцію
[environment]::SetEnvironmentVariable("path", $new_value, "user")
де перший параметр - назва змінної, другий - значення, а третій - "user"
, якщо змінну треба встановити для користувача, і "machine"
- якщо для всієї машини.
Інші цікаві змінні
[ред.]Змінні виду ${C:\path\to.file}
дозволяють отримати доступ до файлів.
Підстановка в рядки
[ред.]Якщо рядок записується в подвійних лапках, то в нього можна підставляти вирази та змінні PowerShell.
Щоб підставити в рядок змінну $x
пишуть "Значення x: $x"
.
Вираз можна підставити в рядок, якщо помістити його в дужки перед якими поставити знак долара. Це називають прямою змінною (direct variable), бо її значення визначається її "іменем". Наприклад:
"$(2+2)"
- дасть на виході "4".
Натомість '$(2+2)'
- так і буде '$(2+2)'.
Типи
[ред.]Також, кожній змінній можна задати тип (хоча це не обов’язково), написавши його назву перед її оголошенням в квадратних дужках. Змінна маючи пов’язаний тип, буде намагатись привести значення які їй присвоюють до вказаного типу. Наприклад:
[bool]$x = $True
$x = 0 # x дорівнюватиме $False
Можливі також складніші приведення:
[datetime]$date = '2014.04.01 12:45"
Щоб визначити тип змінної, викличте її метод GetType
:
$date.GetType().Name
Щоб визначити приналежність змінної типу, можна використати оператор -is
, наприклад:
"hello" -is [string] # True
Стрічки
[ред.]$env:path
- це стрічка що містить шляхи до програм розділені двокрапкою. Її можна перевторити на список стрічок, викликавши метод split()
:
$env:path.split(';')
Інші корисні командлети
[ред.]Масиви
[ред.]Масиви - це змінні типу [array]
. Багато команд в PowerShell повертають в результаті своєї роботи саме масиви. Наприклад:
$a = ipconfig
$a -is [array] # True
Як і в інших мовах програмування, отримати доступ до елементу масиву можна за допомогою квадратних дужок, при цьому нумерація починається з нуля:
$a[1] # отримати ДРУГИЙ елемент масиву
$a.Count
, або $a.Length
- кількість елементів масиву.
Таким чином отримати останній елемент масиву можна наступним чином: $a[$a.Count - 1]
. Але є й простіший спосіб: $a[-1]
. Це нагадує мову Python.
Масив можна створити перелічивши елементи через кому:
# елементи не обов’язково повинні мати однакові типи
$a = 1, 2, 3, "hello", "world"
або задавши як діапазон:
$a = 1..4
Порожній, та масив з одного елемента створюються за допомогою @()
та @($element)
відповідно.
І хоча масиви в PowerShell, як і в інших динамічних мовах програмування гетерогенні, тобто можуть містити елементи будь-якого типу, можна задати типізований масив, який зможе містити лише елементи певного типу, наприклад:
[int[]]$a = 1, 2
Хеші
[ред.]Хеші, або асоціативні масиви - це масиви, індексами яких можуть виступати не тільки числа, а довільні значення. Записуються парами ключ-значення, розліленими крапкою з комою і поміщеними фігурні дужки, перед якими стоїть "собачка":
$user = @{name="admin"; id=1;}
Отримати значення за ключем можна кількома способами:
$user['name']
$user.name
$key = 'name' # назва ключа
$user[$key]
$user.$key # те саме що $user.name, бо $key містить таке значення
$user.keys
- масив всіх ключів хеша. Значення за ключами можна отримувати не по одному, а зразу цілим масивом, якщо попросити масив ключів: $user[$user.keys]
- всі значення хеша.
Щоб додати новий ключ в хеш, достатньо зробити присвоєння:
$user.date = Get-Date
$user.keys
містить всі ключі хеша, а всі значення можна отримати за допомогою виразу $user[$user.keys]
.
Таким чином ми можемо передавши масив ключів отримувати масив значень:
$NATO = @{
"A" = "Alpha";
"B" = "Bravo";
# ...
"Z" = "Zulu";
}
$NATO[([string[]]"BUNYK".ToCharArray())]
# дає: Bravo, Uniform, November, Yankee, Kilo
Як і в Python, хеші та масиви передаються за посиланням а не за значенням, тобто можлива така помилка:
$user1 = @{
name = 'Taras'
}
$user2 = $user1
$user2.name = 'Oleg'
Write-Host $user1.name # теж змінено на Oleg
Щоб цього уникнути, використовують метод Clone()
:
$user1 = @{
name = 'Taras'
}
$user2 = $user1.Clone()
$user2.name = 'Oleg'
Write-Host $user1.name # тепер 'Taras', як і було.
Труби
[ред.]Powershell дозволяє передавати вихід однієї команди на вхід іншої, за допомогою оператора "|
" (труба). Типові командлети що вміють обробляти послідовність:
Format-Table
- форматує вивід як таблицю. При цьому може приймати список атрибутів для колонок таблиці, або скриптблок[tn 5]
PS C:\Users\tbunyk> ls | Select-Object -first 1 | Format-Table Directory: C:\Users\tbunyk Mode LastWriteTime Length Name ---- ------------- ------ ---- d---- 10.06.2013 13:17 .cache
Format-List
- форматує кожен об’єкт у вигляді списку пар атрибут-значення, розділених двокрапкою.[tn 6]
PS C:\Users\tbunyk> ls | Select-Object -first 1 | Format-List Directory: C:\Users\tbunyk Name : .cache CreationTime : 10.06.2013 11:40:39 LastWriteTime : 10.06.2013 13:17:42 LastAccessTime : 10.06.2013 13:17:42
Where-Object
(також має псевдонім (?
) - приймає як параметр скриптблок, і повертає лише ті об’єкти для яких умова описана в тому скриптблоці повертає істину. Наприклад1..10 | Where-Object { $_ -lt 5 }
- лише числа менші 5. [tn 7]ForEach-Object
(також має псевдонім (%
) - приймає як параметр скриптблок, і повертає результати виконання скриптблока до кожного об’єкта що передається в трубу (до якого всередині скриптблоку звертаються як$_
). [tn 8]Select-Object
- приймає послідовність об’єктів, і повертає послідовність об’єктів, при цьому залишаючи лише ті атрибути, які були вказані в його параметрах. Також може приймати параметри-Fist $N
, що вказує повертати тільки перших N об’єктів, та-Last $N
, що поверне лише останніх N об’єктів.[tn 9]
Out-File
, або>
- перенаправляє вивід командлета в файл.[tn 10]Out-Null
- перенаправляє вивід в нікуди. Може знадобитись наприклад для того аби приховати вивід зайвих даних скриптом.[tn 11]Out-Host
- виводить дані в термінал. Має параметр-paging
, що дозволяє посторінково виводити дані. (Якmore
в Unix)[tn 12]Out-String
- виводить дані в рядок. [tn 13]
Умовні оператори
[ред.]В Powershell є два види умовних операторів: if
та switch
. І ще є фільтр Where-Object
, але це просто командлет, а не конструкція мови.
Оператор if
:
if (умова) {
зробити щось;
} elseif (інша умова) {
зробити щось інше;
} else {
зробити хоч щось;
}
Оператор switch
:
$value = "Close";
switch -case ($value) {
"open" { Write-Host "Opening.." }
"close" { Write-Host "Closing.." }
default { Write-Host "Don't know how to $value" }
}
Завдяки ключу -case
, порівняння буде чутливим до регістру, і ми отримаємо на виході:
Don't know how to Close
Якщо його забрати - порівняння буде ігнорувати регістр в рядків. Для нерядкових змінних цей ключ не має сенсу.
Ключ -wildcard
дозволяє робити порівняння з маскою.
switch -wildcard ($value) {
"*@gmail.com" { Write-Host "Gmail" }
"*@ukr.net" { Write-Host "Freemail" }
}
Ключ -regex
дозволяє порівнювати значення з регулярними виразами.
Також в -switch
замість значень можна писати умови:
switch ($value) {
{ $_ -le 5 <# умова #> } { <# код #> }
}
Умова є булевим виразом, про який мова піде далі.
Булеві вирази
[ред.]Cимвол =
означає присвоєння, а <, >
- перенаправлення потоків, тому для порівняння значень використовують наступні оператори:
-eq
(equal) - дорівнює-ne
(not equal) - не дорівнює-gt
(greater then) - більше-lt
(less then) - менше-ge
(greater equals) - більше або дорівнює-le
(less equals) - менше або дорівнює
Наприклад:
2 + 2 -eq 4 # True
Порівняння рядків ігнорують регістр:
"Alpha" -eq "alpha" # True
Коли потрібно явно задати чутливість або не чутливість до регістру, в порівняннях використовують префікси "c" (case-sensitive, чутливий до регістру) та "i" (insensitive, ignore - нечутливий, ігнорувати регістр).
"Alpha" -ceq "alpha" # False
Крім того є оператори які показують чи можна знайти елемент в масиві:
1, 2, 4 -contains 1 # True
1, 2, 4 -notcontains 3 # True
А також, звісно логічні оператори:
"2b" -or -not "2b" # True
not
або !
- логічне ні, -and
- і, -or
- або, -xor
- виключне або.
Цикли
[ред.]Циклів в PowerShell багато видів:
while
do while
for
ForEach
- І вже раніше згаданий
ForEach-Object
теж можна і варто використовувати як цикл. - І навіть
switch
може працювати як цикл!
Цикл while
:
while (умова) {
// робити дію
}
Цикл do while
дуже корисний тим, що перевіряє умову після виконання тіла циклу, і якщо вона істинна - продовжує:
do {
$input = Read-Host "Email: "
} while (! ($input -like "*@*.*"));
Цикл for
відомий всім з таких мов як C, чи JavaScript:
for($i = 0; $i -lt 10; $i++) {
Write-Host $i
}
Але не обов’язково використовувати for
лише для цілих лічильників циклу. Можна використати його як звичайний цикл з передумовою, наприклад щоб пробігтись по всіх рядках файлу:
for(
$file=[system.io.file]::OpenText('C:\shell_snippets.ps1');
!($file.EndOfStream);
$line=$file.ReadLine()
) {
write-Host $line
}
foreach
дозволяє проітерувати по кожному елементі послідовності:
foreach($i in 1..10) {
Write-Host $i
}
ForEach-Object
працює аналогічно, тільки отримує послідовність крізь трубу:
1..10 | ForEach-Object {
Write-Host $_
}
Оператор switch
, коли йому передати масив, виконує свої блоки для кожного з елементів масиву:
switch (1..10) {
1 { Write-Host "Перше число!"}
{$_ % 2 -eq 0 } { Write-Host "$_ - парне" }
{$_ % 3 -eq 0 } { Write-Host "$_ - ділиться на три" }
default { Write-Host "$_ - нічого особливого" }
}
Варто зауважити що для 6
виконаються обидва блоки. Щоб цього уникнути в звичайному switch
можна закінчувати блок командою break
, але в циклі таке призведе до закінчення циклу:
{$_ % 2 -eq 0 } { Write-Host "$_ - парне"; break }
break
[tn 14] (вийти з циклу) та continue
[tn 15] (перервати виконання поточної ітерації і почати від початку наступної) можна використовувати у всіх циклах окрім командлета ForEach-Object
.
Наприклад щоб вивести всі числа крім 5:
foreach($i in 1..10) {
if($i -eq 5) { continue };
Write-Host $i
}
break
та continue
можна вказувати з яким циклом вони працюють. Наприклад якщо маємо два вкладені цикли, ми можемо позначити їх мітками:
:outer_cycle foreach(...) {
:inner_cycle foreach(...) {
if (...) { break outer_cycle }
}
}
Функції
[ред.]Функції, як і командлети викликаються без дужок:
function hello {
Write-Host "Привіт, світе!"
}
hello
# Привіт, світе!
Навіть якщо є аргументи:
function hello2($username) {
Write-Host "Привіт, $username!"
}
hello2 Тарас
# Привіт, Тарас!
$args
містить масив аргументів, або $null
return
писати не обов’язково, функція сама поверне як результат значення останнього виразу:
function subtract($a, $b) {
$a - $b
}
Аргументи можна передати іменовано:
subtract -a 3 -b 2
або порядково:
subtract 3 2
Якщо передати більше аргументів ніж вказано при описі - вони попадуть в $args
.
Параметрам можна задавати тип:
function add([int]$value ...
Одним з типів є аргумент - перемикач:
function do_something([switch]$debug) {
...
do_something -debug
Ще одним цікавим типом є посилання [ref]
. За допомогою передачі за посиланням можна зробити функцію яка змінюватиме значення своїх аргументів:
function inc([ref]$x) {
$x.Value += 1
}
$a = 1
inc ([ref]$a)
Write-Host $a
# 2
Можна також передати для аргумента значення за замовчуванням:
function inc([ref]$x, $d=1) {
$x.Value += $d
}
Щоб зробити аргумент функції обов’язковим, можна задати йому значенням за замовчуванням вираз, який генеруватиме виняток:
function save($fn=$(throw "Filename not passed";) {
...
Записати код функції в файл:
$function:hello > myscript.ps1
Фільтри
[ред.]Фільтр - це функція що є аналогом програми фільтра в UNIX. Фільтри в PowerShell бувають двох видів:
- повільні послідовнісні - такі що потребують читання всіх даних в пам’ять, перед видачею результату (наприклад сортування)
- швидкі потокові (аналог генераторів в Python) - такі які одразу опрацьовують кожен елемент вхідної послідовності.
Повільні фільтри - це звичайні функції, дані яким приходять через трубу. Всередині функції ці дані містяться в масиві $input
:
function squares {
foreach($elem in $input) {
$elem * $elem;
}
}
1..10 | squares
Швидкі фільтри можна описати за допомогою ключового слова filter
:
filter squares {
$_ * $_
}
1..10 | squares
Або блоку process
всередині функції:
function squares {
process {
$_ * $_
}
}
Блок process
використовується разом з блоками begin
, end
для ініціалізації та завершення роботи фільтра:
function accumulate {
begin {
$sum = 0;
}
process {
$sum += $_;
$sum;
}
end {
Write-Host "Total sum: $sum"
}
}
1..10 | accumulate
Файли
[ред.]Як ми вже казали, Out-File
, або >
- перенаправляє вивід з труби в файл.[tn 10] Йому, якщо не використовувати форму >
, можна передавати параметри, наприклад -Append
- дописувати дані в файл, замість того щоб переписувати його за замовчуванням
Add-Content -Path $file -Value $value
- дописує до файла певне значення, наприклад рядок.[tn 16]
Виконання скрипта
[ред.]Якщо при виконанні скрипта ви отримуєте наступну помилку:
PS C:\Documents and Settings\adminaccount> . .\script.ps1 File C:\Documents and Settings\adminaccount\lpu.ps1 cannot be loaded because th e execution of scripts is disabled on this system. Please see "get-help about_s igning" for more details. At line:1 char:2 + . <<<< .\lpu.ps1 + CategoryInfo : NotSpecified: (:) [], PSSecurityException + FullyQualifiedErrorId : RuntimeException
То це означає що поточна політика виконання не дозволяє скриптам виконуватись[tn 17]. Щоб отримати політику виконання яка зараз встановлена на вашому комп’ютері, наберіть Get-ExecutionPolicy
.
Set-ExecutionPolicy remotesigned
Віддалені сесії
[ред.]Дозволити віддалені сесії на сервері:[tn 18]
Enable-PSRemoting -SkipNetworkProfileCheck
-SkipNetworkProfileCheck
потрібно лише якщо у вас Network location - Public. Для Home чи Work - не потрібно.
Почати віддалену сесію:[tn 19]
$cred = Get-Credential -Credential $username
Enter-PSSession -ComputerName $hostname -Credential $cred
Exit-PSSession
- вийти з віддаленої сесії.[tn 20]
Виконати шматок коду на віддаленому сервері: [tn 21]
Invoke-Command -ComputerName $hostname -Credential $cred -ScriptBlock { commands }
Спосіб задавати логін та пароль неінтерактивно:
function credential([String]$user, [String]$password) {
if($password -eq $null) {
$pass = Read-Host "Password for $($user): " -AsSecureString
} else {
$pass = ConvertTo-SecureString –String $password –AsPlainText -Force
}
New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList $user, $pass
}
Enter-PSSession -ComputerName 192.168.173.206 -Credential $(credential 'Administrator' 'password')
Запрошення до вводу
[ред.]Вигляд запрошення до вводу в інтерактивній сесії можна змінити, описавши функцію prompt
. Наприклад:
function Prompt
{
$date = Get-Date
$location = Get-Location
"$($date.Hour):$($date.Minute) $location>"
}
Провайдери Powershell
[ред.]Get-PSProvider
- отримати список провайдерів.
Реєстр
[ред.]Реєстр складається з ключів та значень. Ключі подібні на директорії і містять інші ключі або значення. Значення – подібні на файли і мають ім’я, тип та власне саме значення. Ключ може містити багато значень. Колись у 16-ти розрядному реєстрі Windows 3 ключі могли містити лише одне значення стрічкового типу, власне тому називались ключами, а реєстр був більш схожий на асоціативний масив. Тепер самі “ключі” стали асоціативними масивами що містять імена значень, але назва залишилась. Також, для зворотньої сумісності кожен ключ містить значення за замовчуванням, ім’ям якого є порожній рядок.
Всі дані реєстру містяться в кількох кореневих ключах, найважливішими з яких є HKEY_CURRENT_USER
, який містить налаштування для залогіненого на даний момент користувача та HKEY_LOCAL_MACHINE
, який містить налаштування загалом для машини.
Доступні кореневі ключі реєстру можна отримати за допомогою команди Get-PSDrive
, яка перелічує диски доступні для PowerShell. І це не тільки диски файлової системи, а й диски що містять всі змінні, середовище, а також ключі реєстру. PowerShell надає до реєстру такий самий інтерфейс як до файлової системи. Щоб переглянути ключі в налаштуваннях локальної машини досить написати:
Set-Location HKLM:\ # або cd
Get-ChildItem # або ls
Давайте збережемо якісь дані в HKLM:\Software\Test. Перевіримо що такий ключ існує:
cd HKLM:\SOFTWARE
Test-Path Test # Якщо не існує – дасть False
if (!(Test-Path HKLM:\SOFTWARE\zenoss\logs)) { if (!(Test-Path HKLM:\SOFTWARE\zenoss)) { New-Item HKLM:\SOFTWARE\zenoss } New-Item HKLM:\SOFTWARE\zenoss\logs }
Event Log
[ред.]Get-EventLog -list
- отримати список логів.[tn 22]
Get-EventLog $name -newest 3
- отримати три найновіші записи з логу $name
.
New-EventLog -LogName $name -Source manual
- створити лог з джерелом manual
. [tn 23]
Remove-EventLog $name
- видалити лог $name
. [tn 24]
Записати повідомлення в лог:
Write-EventLog -LogName $name -Source manual -Message "Hello world!" -EventId 0 -EntryType information
EntryType
може бути Error
, Warning
, Information
, SuccessAudit
, або FailureAudit
. [tn 25]
Графічний інтерфейс
[ред.]Посилання
[ред.]- Mastering PowerShell Dr. Tobias Weltner, 2009 BBS Technologies
Довідка Microsoft TechNet
[ред.]- ↑ Get-Help
- ↑ Get-ChildItem
- ↑ Start-Sleep
- ↑ Clear-Host
- ↑ Format-Table
- ↑ Format-List
- ↑ Where-Object
- ↑ ForEach-Object
- ↑ Select-Object
- ↑ 10,0 10,1 Out-File
- ↑ Out-Null
- ↑ Out-Host
- ↑ Out-String
- ↑ about_Break
- ↑ about_Continue
- ↑ Add-Content
- ↑ about_Signing
- ↑ Enable-PSRemoting
- ↑ Enter-PSSession
- ↑ Exit-PSSession
- ↑ Invoke-Command
- ↑ Get-EventLog
- ↑ New-EventLog
- ↑ Remove-EventLog
- ↑ Write-EventLog