6. Скрипты PowerShell
PowerShell скрипты (.ps1)
Заголовок раздела «PowerShell скрипты (.ps1)»PowerShell скрипты сохраняются с расширением .ps1. Это полноценный язык программирования: переменные, условия, циклы, функции, классы, обработка ошибок.
ExecutionPolicy — политика выполнения
Заголовок раздела «ExecutionPolicy — политика выполнения»По умолчанию Windows блокирует запуск скриптов. Нужно настроить политику:
# Посмотреть текущую политикуGet-ExecutionPolicyGet-ExecutionPolicy -List # все уровни
# Изменить политикуSet-ExecutionPolicy RemoteSigned # рекомендуется для разработкиSet-ExecutionPolicy Unrestricted # без ограничений (не рекомендуется)Set-ExecutionPolicy Restricted # только интерактивный режим (по умолчанию)
# Для текущего пользователя (без прав администратора)Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
# Временно обойти при запускеpowershell -ExecutionPolicy Bypass -File script.ps1Политики:
Restricted— скрипты запрещеныRemoteSigned— локальные скрипты OK, загруженные требуют подписиUnrestricted— всё разрешено (с предупреждением для загруженных)Bypass— без ограничений и предупреждений
Создание и запуск скрипта
Заголовок раздела «Создание и запуск скрипта»# Создать скриптNew-Item -Path "myscript.ps1" -ItemType File
# Содержимое скриптаWrite-Output "Hello, PowerShell!"
# Запустить.\myscript.ps1 # всегда с .\powershell -File .\myscript.ps1& ".\myscript.ps1" # оператор вызова &Переменные
Заголовок раздела «Переменные»# Типы переменных$name = "PowerShell" # String$version = 7.4 # Double$count = 42 # Int$enabled = $true # Boolean$nothing = $null # Null$today = Get-Date # DateTime
# Явное указание типа[string]$text = "hello"[int]$number = 42[bool]$flag = $false[datetime]$date = "2024-01-01"
# Массивы$fruits = @("apple", "banana", "cherry")$numbers = @(1, 2, 3, 4, 5)$fruits[0] # apple$fruits[-1] # cherry$fruits.Count # 3$fruits += "mango" # добавить элемент
# Хеш-таблицы (словари)$person = @{ Name = "Alice" Age = 30 City = "Moscow"}$person.Name # Alice$person["Age"] # 30$person.Keys # все ключиУсловия if/elseif/else
Заголовок раздела «Условия if/elseif/else»$age = 25
if ($age -ge 18) { Write-Output "Совершеннолетний"} elseif ($age -ge 14) { Write-Output "Подросток"} else { Write-Output "Ребёнок"}
# Switch$day = "Monday"switch ($day) { "Monday" { Write-Output "Понедельник" } "Tuesday" { Write-Output "Вторник" } "Saturday" { Write-Output "Суббота! Выходной!" } "Sunday" { Write-Output "Воскресенье! Выходной!" } default { Write-Output "Рабочий день" }}
# Тернарный оператор (PS 7+)$result = $age -ge 18 ? "Взрослый" : "Несовершеннолетний"# foreach по коллекции$fruits = @("apple", "banana", "cherry")foreach ($fruit in $fruits) { Write-Output "Фрукт: $fruit"}
# for с счётчикомfor ($i = 1; $i -le 5; $i++) { Write-Output "Итерация: $i"}
# while$count = 1while ($count -le 10) { Write-Output $count $count++}
# do-while (выполнится хотя бы раз)do { $input = Read-Host "Введите 'quit' для выхода"} while ($input -ne "quit")
# ForEach-Object через pipeline1..10 | ForEach-Object { $_ * 2 }
# break и continueforeach ($item in 1..10) { if ($item -eq 5) { continue } # пропустить 5 if ($item -eq 8) { break } # остановиться на 8 Write-Output $item}Функции
Заголовок раздела «Функции»# Базовая функцияfunction Say-Hello { Write-Output "Привет!"}Say-Hello
# Функция с параметрамиfunction Get-Greeting { param ( [string]$Name, [int]$Age = 0 # параметр с дефолтным значением ) if ($Age -gt 0) { Write-Output "Привет, $Name! Тебе $Age лет." } else { Write-Output "Привет, $Name!" }}Get-Greeting -Name "Alice"Get-Greeting -Name "Bob" -Age 25
# Продвинутые параметрыfunction Deploy-App { [CmdletBinding()] param ( [Parameter(Mandatory=$true)] [string]$Environment,
[Parameter(Mandatory=$false)] [ValidateSet("staging", "production")] [string]$Target = "staging",
[switch]$DryRun # флаг без значения )
if ($DryRun) { Write-Output "DRY RUN: деплой $Environment в $Target" } else { Write-Output "Деплой $Environment в $Target..." }}Deploy-App -Environment "v1.2.3" -Target "production" -DryRun
# Возврат значенияfunction Add-Numbers { param ([int]$A, [int]$B) return $A + $B # или просто $A + $B}$result = Add-Numbers -A 10 -B 20Write-Output "Сумма: $result"Обработка ошибок
Заголовок раздела «Обработка ошибок»try { $content = Get-Content "nonexistent.txt" -ErrorAction Stop Write-Output "Содержимое: $content"}catch [System.IO.FileNotFoundException] { Write-Output "Файл не найден!"}catch { Write-Output "Ошибка: $($_.Exception.Message)"}finally { Write-Output "Это выполнится в любом случае"}
# $ErrorActionPreference$ErrorActionPreference = "Stop" # остановить скрипт при ошибке
# -ErrorAction параметр для отдельных командGet-Item "missing.txt" -ErrorAction SilentlyContinue # игнорироватьGet-Item "missing.txt" -ErrorAction Stop # остановитьGet-Item "missing.txt" -ErrorAction Continue # продолжить (по умолчанию)Практика: Реальный скрипт
Заголовок раздела «Практика: Реальный скрипт»#!/usr/bin/env pwsh# backup-logs.ps1 — скрипт для архивации логов[CmdletBinding()]param ( [Parameter(Mandatory=$false)] [string]$LogDir = "C:\Logs",
[Parameter(Mandatory=$false)] [string]$BackupDir = "C:\Backup",
[Parameter(Mandatory=$false)] [int]$DaysOld = 7,
[switch]$WhatIf)
function Write-Log { param ([string]$Message, [string]$Level = "INFO") $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" Write-Output "[$timestamp] [$Level] $Message"}
# Проверкиif (-not (Test-Path $LogDir)) { Write-Log "Директория логов не найдена: $LogDir" "ERROR" exit 1}
New-Item -Path $BackupDir -ItemType Directory -Force | Out-Null
# Найти старые логи$oldLogs = Get-ChildItem -Path $LogDir -Filter "*.log" | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$DaysOld) }
Write-Log "Найдено $($oldLogs.Count) файлов для архивации"
foreach ($log in $oldLogs) { $dest = Join-Path $BackupDir $log.Name if ($WhatIf) { Write-Log "WhatIf: переместить $($log.FullName)" } else { Move-Item -Path $log.FullName -Destination $dest Write-Log "Перемещён: $($log.Name)" }}
Write-Log "Готово!"PowerShell — мощный язык для автоматизации Windows. Инвестиции в его изучение окупаются на любом корпоративном проекте!