Что это
В этой статье представлено полное руководство по лучшим практикам написания сценариев PowerShell с акцентом на структуру кода, форматирование вывода, обработку ошибок, оптимизацию производительности и меры безопасности.
Зачем
Следование лучшим практикам PowerShell обеспечивает читаемость, поддержку, безопасность и эффективность ваших сценариев. Это снижает технический долг, улучшает совместную работу и минимизирует риски в производственной среде.
Как
Проектирование Инструментов и Контроллеров
Определите, пишете ли вы "Инструмент" или "Контроллер"
- Инструмент: Повторно используемые функции/модули.
- Контроллер: Автоматизация конкретной задачи, не предназначен для повторного использования.
Делайте код модульным
- Используйте функции и модули для максимальной повторной используемости.
Используйте стандартные соглашения об именах
- Придерживайтесь формата Глагол-Существительное с использованием утверждённых глаголов PowerShell (
Get-Verb
).
Стандартизируйте имена параметров
- Используйте, например,
$ComputerName
вместо пользовательских префиксов.
Инструменты должны выводить необработанные данные
- Минимальная обработка данных для гибкости.
Контроллеры должны выводить отформатированные данные
- Форматирование для удобочитаемых отчетов.
Пример
function Get-DiskInfo {
param ([string]$ComputerName)
Get-WmiObject Win32_LogicalDisk -ComputerName $ComputerName
}
Избегайте изобретения велосипеда
Используйте встроенные cmdlet’ы, такие как Test-Connection
, вместо написания собственных функций.
# Рекомендуется
Test-Connection $ComputerName -Quiet
Написание Блоков Параметров
Всегда пишите справку
Добавляйте комментарии с .SYNOPSIS
, .DESCRIPTION
и хотя бы одним .EXAMPLE
.
function Test-Help {
<#
.SYNOPSIS
Пример правильной документации.
.EXAMPLE
Test-Help -MandatoryParameter "Пример"
Запуск функции с обязательным параметром.
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[Alias("MP")]
[String]$MandatoryParameter
)
}
Используйте [CmdletBinding()]
Включает общие параметры: -Verbose
, -Debug
, -ErrorAction
.
Поддерживайте -WhatIf и -Confirm
Для команд, изменяющих состояние, используйте SupportsShouldProcess
.
[CmdletBinding(SupportsShouldProcess, ConfirmImpact = "Medium")]
param ([switch]$Force)
Явно указывайте типы параметров
Определяйте типы для валидации и ясности.
param (
[string]$Name,
[int]$Count
)
Правильное использование [switch]
- По умолчанию —
$false
. - Используйте как логическое значение.
Форматирование Вывода
Избегайте использования Write-Host без необходимости
Используйте Write-Verbose
, Write-Debug
или Write-Output
по назначению.
Используйте Write-Progress для отображения прогресса
Write-Progress -Activity "Обработка" -Status "50% выполнено" -PercentComplete 50
Используйте файлы формата для объектов
Создавайте .format.ps1xml
вместо inline-форматирования.
Выводите только один тип объектов за раз
Применяйте [OutputType()]
и избегайте смешивания типов.
Лучшие Практики Обработки Ошибок
Используйте -ErrorAction Stop с cmdlet’ами
Обрабатывайте ошибки через try-catch
.
try {
Get-Item "C:\НекорректныйПуть" -ErrorAction Stop
} catch {
Write-Warning "Элемент не найден."
}
Используйте $ErrorActionPreference вне cmdlet’ов
Временно устанавливайте 'Stop'
для рисковых операций.
Избегайте использования флагов и $?
Используйте структурированные блоки try-catch
.
Сохраняйте $Error[0] или $_ сразу в catch
catch {
$errorDetails = $_
Write-Error "Произошла ошибка: $($errorDetails.Exception.Message)"
}
Оптимизация Производительности
PERF-01 Измеряйте производительность по необходимости
Применяйте Measure-Command
для сравнения решений.
Measure-Command {
foreach ($item in $data) { Process-Item $item }
}
PERF-02 Баланс между читаемостью и производительностью
- Небольшие данные — читаемость.
- Большие данные — потоковая обработка и .NET.
Читаемо:
$content = Get-Content -Path file.txt
foreach ($line in $content) {
Do-Something -Input $line
}
Быстрее:
Get-Content -Path file.txt | ForEach-Object {
Do-Something -Input $_
}
Максимальная производительность с .NET:
$sr = New-Object System.IO.StreamReader "file.txt"
while ($sr.Peek() -ge 0) {
$line = $sr.ReadLine()
Do-Something -Input $line
}
PERF-03 Используйте возможности языка
- Конструкции языка (
foreach
) > .NET > скрипты > cmdlet’ы. - Всегда измеряйте перед оптимизацией.
Лучшие Практики Безопасности
Всегда используйте PSCredential для учетных данных
Не храните пароли в открытом виде.
param (
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential
)
Для API:
$Insecure.SetPassword($Credential.GetNetworkCredential().Password)
Используйте SecureString для конфиденциальных данных
$Secure = Read-Host -Prompt "Введите конфиденциальные данные" -AsSecureString
Безопасное преобразование:
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Secure)
$PlainText = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR)
Безопасное хранение учетных данных
Get-Credential | Export-CliXml -Path C:\secure\cred.xml
$Credential = Import-CliXml -Path C:\secure\cred.xml
Хранение зашифрованных строк
ConvertFrom-SecureString -SecureString $Secure | Out-File -Path "${Env:AppData}\secure.bin"
$Secure = Get-Content -Path "${Env:AppData}\secure.bin" | ConvertTo-SecureString
Заключение
Следуя этим лучшим практикам PowerShell, вы создадите надежные, эффективные и безопасные сценарии. Всегда стремитесь к балансу между читаемостью, производительностью и безопасностью для достижения наилучших результатов в автоматизации.