Стандартные блоки и модули PowerShell
Зачем стандартные блоки
Стандартный блок — функция с ясным контрактом, которую можно вставить в разные скрипты без копипаста. Вместо одного монолита «на 400 строк» собирают цепочку: «найти старые файлы» → «сформировать имя архива» → «упаковать и удалить».
Поэтапный подход из 124: сначала рабочий скрипт для одной задачи, затем выделение повторяемых кусков в функции, затем модуль .psm1 для команды.
Анатомия блока-функции
Каждая функция для автоматизации получает три обязательных элемента:
| Элемент | Зачем |
|---|---|
[CmdletBinding()] | Общие параметры -Verbose, -ErrorAction, -WhatIf |
[OutputType(...)] | Документирует тип результата для IDE и Get-Help |
param() с типами и Mandatory | Ранний отказ при неверных аргументах |
Пример — уникальное имя архива
Функция создаёт путь к новому .zip, проверяет папку и коллизию имён — типовой паттерн архивации логов:
function Set-ArchiveFilePath {
[CmdletBinding()]
[OutputType([string])]
param(
[Parameter(Mandatory)]
[string]$ZipPath,
[Parameter(Mandatory)]
[string]$ZipPrefix,
[Parameter(Mandatory)]
[datetime]$Date
)
if (-not (Test-Path -LiteralPath $ZipPath)) {
New-Item -Path $ZipPath -ItemType Directory -Force | Out-Null
Write-Verbose "Создана папка: $ZipPath"
}
$zipName = '{0}{1:yyyyMMdd}.zip' -f $ZipPrefix, $Date
$zipFile = Join-Path -Path $ZipPath -ChildPath $zipName
if (Test-Path -LiteralPath $zipFile) {
throw "Архив уже существует: $zipFile"
}
return $zipFile
}
Пример — файлы старше N дней
Параметр «возраст» задают положительным числом; внутри функции преобразуют в отрицательный для AddDays:
function Get-FilesOlderThan {
[CmdletBinding()]
[OutputType([System.IO.FileInfo[]])]
param(
[Parameter(Mandatory)]
[string]$Path,
[Parameter(Mandatory)]
[ValidateRange(1, [int]::MaxValue)]
[int]$Days
)
$cutoff = (Get-Date).AddDays(-$Days)
Get-ChildItem -LiteralPath $Path -File |
Where-Object { $_.LastWriteTime -lt $cutoff }
}
AddDays. Валидация ValidateRange(1, …) отсекает отрицательные значения до логики архивации.Сборка скрипта из блоков
Скрипт верхнего уровня — оркестратор: параметры, вызов функций, журнал, код выхода.
param(
[Parameter(Mandatory)]
[string]$LogFolder,
[Parameter(Mandatory)]
[string]$ArchiveFolder,
[string]$ArchivePrefix = 'logs_',
[int]$OlderThanDays = 30
)
function Write-Log([string]$Message) {
$line = '{0:u} {1}' -f (Get-Date), $Message
Add-Content -Path "$PSScriptRoot\archive.log" -Value $line
Write-Host $line
}
try {
Write-Log "Старт: $LogFolder"
$files = Get-FilesOlderThan -Path $LogFolder -Days $OlderThanDays
if (-not $files) {
Write-Log 'Нет файлов для архивации.'
exit 0
}
$lastDate = ($files | Sort-Object LastWriteTime -Descending | Select-Object -First 1).LastWriteTime
$zipPath = Set-ArchiveFilePath -ZipPath $ArchiveFolder -ZipPrefix $ArchivePrefix -Date $lastDate
Compress-Archive -Path $files.FullName -DestinationPath $zipPath
$files | Remove-Item -Force
Write-Log "Архив: $zipPath"
exit 0
}
catch {
Write-Log "ОШИБКА: $($_.Exception.Message)"
exit 1
}
Проблема «функции внутри .ps1»: при dot-sourcing нескольких скриптов имена функций могут конфликтовать. Решение — вынести блоки в модуль.
Модуль .psm1
Модуль — каталог с файлом ИмяМодуля.psm1 (и опционально ИмяМодуля.psd1 — манифест).
Структура каталога:
ArchiveTools/
├── ArchiveTools.psd1 # манифест (версия, экспорт)
└── ArchiveTools.psm1 # функции
ArchiveTools.psm1:
function Set-ArchiveFilePath { ... } # код из примера выше
function Get-FilesOlderThan { ... }
Export-ModuleMember -Function Set-ArchiveFilePath, Get-FilesOlderThan
Минимальный ArchiveTools.psd1:
@{
ModuleVersion = '1.0.0'
RootModule = 'ArchiveTools.psm1'
FunctionsToExport = @('Set-ArchiveFilePath', 'Get-FilesOlderThan')
Description = 'Блоки архивации логов для внутренних скриптов'
}
Установка для разработки (путь добавьте в $env:PSModulePath или скопируйте в Documents\PowerShell\Modules):
Import-Module .\ArchiveTools\ArchiveTools.psd1 -Force
Get-Command -Module ArchiveTools
| Действие | Команда |
|---|---|
| Список экспортированных функций | Get-Command -Module ArchiveTools |
| Справка по функции модуля | Get-Help Set-ArchiveFilePath |
| Обновление после правки | Import-Module ... -Force |
Советы по модулям для автоматизации
| Правило | Пояснение |
|---|---|
| Один блок — одна задача | «Имя архива» и «список файлов» — разные функции |
| Comment-based help в каждой функции | Get-Help без чтения исходника — см. 111 |
Install-Module вне рабочего скрипта | Установку модулей делают при подготовке образа ПК или в CI |
| Версии модулей фиксируют | Два скрипта могут требовать разные версии одного модуля |
| Тестируйте блок отдельно | В консоли: Get-FilesOlderThan -Path C:\Logs -Days 7 -Verbose |
Когда выносить в модуль
| Ситуация | Решение |
|---|---|
Функция нужна в одном .ps1 | Оставить в том же файле или dot-source .\Blocks.ps1 |
| Тот же блок в 2+ скриптах | Модуль или общий .ps1 с dot-sourcing |
| Блок отдают другой команде | Модуль + Git + 111 чек-лист |
| Нужна публикация в Gallery | Манифест .psd1, semver, Publish-Module |
Чек-лист блока
| # | Проверка |
|---|---|
| 1 | Есть [CmdletBinding()] и [OutputType] |
| 2 | Параметры типизированы; обязательные — Mandatory |
| 3 | Ошибки — throw или -ErrorAction Stop, а не тихий $null |
| 4 | Есть Write-Verbose для отладки в планировщике |
| 5 | Функция возвращает объект/значение, а не только пишет в консоль |
Дальше
| Тема | Материал |
|---|---|
| Запуск по расписанию и наблюдатели | 126 |
Планировщик Windows, пример .ps1 | 2.05/112 |
Параметры, SupportsShouldProcess | 118 |
| Модули Gallery, Az, Graph | 121 |
См. также
Другие статьи этого же раздела в боковом меню (как на странице "О разделе"). История PowerShell - эволюция платформы от Windows-оболочки до кроссплатформенного языка автоматизации. Простые приложения на PowerShell — скрипты Windows, файлы, JSON и REST. Экосистема автоматизации на PowerShell - установка, окружение и типовые инструменты для системных задач. Набор советов, правил, принципов и обычаев в разработке на этом языке. Основы языка PowerShell - синтаксис, объектный пайплайн и базовые подходы к автоматизации администрирования. PowerShell представляет собой среду командной строки и скриптовый язык, построенный на базе платформы .NET. $this — переменная, указывающая на текущий объект в методах классов. В PowerShell переменная $this используется внутри методов для обращения к свойствам и методам текущего экземпляра класса. Командлеты и встроенные функции PowerShell - устройство, принципы использования и расширение возможностей оболочки. Типизация, набор правил определения типа данных значений языка. Условные выражения и циклы в PowerShell - ветвление сценариев и управление повторяющимися операциями. Функции и продвинутые параметры в PowerShell - переиспользование кода, валидация аргументов и удобство CLI. Для динамического добавления свойств используется cmdlet Add-Member. Это позволяет расширять функциональность объектов без изменения их исходного кода.История PowerShell
Простые приложения на PowerShell
Экосистема автоматизации на PowerShell
Рекомендации по написанию PowerShell-скриптов
Основы языка PowerShell
Синтаксис и операторы PowerShell
Ключевые слова и управляющие конструкции
Командлеты и встроенные функции PowerShell
Типы данных и работа с переменными
Условные выражения и циклы
Функции и продвинутые параметры
Объектная модель и конвейерная обработка