Руководство по Лучшим Практикам Сценариев PowerShell

  1. Что это
  2. Зачем
  3. Как
    1. Проектирование Инструментов и Контроллеров
      1. Определите, пишете ли вы "Инструмент" или "Контроллер"
      2. Делайте код модульным
      3. Используйте стандартные соглашения об именах
      4. Стандартизируйте имена параметров
      5. Инструменты должны выводить необработанные данные
      6. Контроллеры должны выводить отформатированные данные
    2. Пример
    3. Избегайте изобретения велосипеда
    4. Написание Блоков Параметров
      1. Всегда пишите справку
      2. Используйте [CmdletBinding()]
      3. Поддерживайте -WhatIf и -Confirm
      4. Явно указывайте типы параметров
      5. Правильное использование [switch]
    5. Форматирование Вывода
      1. Избегайте использования Write-Host без необходимости
      2. Используйте Write-Progress для отображения прогресса
      3. Используйте файлы формата для объектов
      4. Выводите только один тип объектов за раз
    6. Лучшие Практики Обработки Ошибок
      1. Используйте -ErrorAction Stop с cmdlet’ами
      2. Используйте $ErrorActionPreference вне cmdlet’ов
      3. Избегайте использования флагов и $?
      4. Сохраняйте $Error[0] или $_ сразу в catch
    7. Оптимизация Производительности
      1. PERF-01 Измеряйте производительность по необходимости
      2. PERF-02 Баланс между читаемостью и производительностью
      3. PERF-03 Используйте возможности языка
    8. Лучшие Практики Безопасности
      1. Всегда используйте PSCredential для учетных данных
      2. Используйте SecureString для конфиденциальных данных
      3. Безопасное хранение учетных данных
      4. Хранение зашифрованных строк
  4. Заключение

Что это

В этой статье представлено полное руководство по лучшим практикам написания сценариев 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, вы создадите надежные, эффективные и безопасные сценарии. Всегда стремитесь к балансу между читаемостью, производительностью и безопасностью для достижения наилучших результатов в автоматизации.

タイトルとURLをコピーしました