Конфигурация и адаптивные скрипты
Зачем выносить данные из кода
Жёстко прошитые пути, списки серверов и пороги в .ps1 заставляют править код при каждом изменении инфраструктуры. Адаптивный скрипт читает данные конфигурации и применяет одну и ту же логику к разным окружениям (dev/stage/prod, филиалы, клиенты).
Разделение:
| Слой | Содержимое | Где хранить |
|---|---|---|
| Код | Алгоритм, проверки, обработка ошибок | .ps1, .psm1 в Git |
| Конфиг | Пути, списки, пороги, имена секретов (не сами секреты) | JSON/YAML рядом или в share |
| Секреты | Пароли, ключи | 127 — SecretManagement |
JSON-конфигурация
Файл config.json рядом со скриптом:
{
"LogFolder": "C:\\App\\logs",
"ArchiveFolder": "D:\\Archives",
"OlderThanDays": 30,
"ArchivePrefix": "logs_",
"SecretNameSql": "SqlMonitor",
"NotifyEmail": "ops@example.com"
}
Загрузка и валидация:
param(
[string]$ConfigPath = (Join-Path $PSScriptRoot 'config.json')
)
if (-not (Test-Path -LiteralPath $ConfigPath)) {
throw "Конфиг не найден: $ConfigPath"
}
$config = Get-Content -LiteralPath $ConfigPath -Raw -Encoding utf8 |
ConvertFrom-Json
foreach ($key in @('LogFolder', 'ArchiveFolder')) {
if (-not $config.$key) { throw "В конфиге отсутствует $key" }
}
$config.OlderThanDays = [int]$config.OlderThanDays
| Практика | Зачем |
|---|---|
$PSScriptRoot для пути к конфигу | Работает из планировщика с -WorkingDirectory |
-Encoding utf8 | Кириллица в путях и письмах |
| Явная проверка обязательных ключей | Ранний понятный сбой вместо $null в середине |
Отдельный config.prod.json | Параметр -ConfigPath при деплое |
Секреты в JSON не кладут — только имя в SecretStore: "SecretNameSql": "SqlMonitor".
Data-driven функции
Одна функция обрабатывает запись конфигурации — объект или hashtable:
function Test-ServerHealth {
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[pscustomobject]$Server
)
$result = [ordered]@{
Name = $Server.Name
Ok = $true
Detail = ''
}
try {
if ($Server.Port) {
$tcp = Test-NetConnection -ComputerName $Server.Host -Port $Server.Port -WarningAction SilentlyContinue
if (-not $tcp.TcpTestSucceeded) { throw "Port $($Server.Port) closed" }
}
}
catch {
$result.Ok = $false
$result.Detail = $_.Exception.Message
}
[pscustomobject]$result
}
Конфиг со списком серверов:
{
"Servers": [
{ "Name": "web-01", "Host": "web-01.corp.local", "Port": 443 },
{ "Name": "db-01", "Host": "db-01.corp.local", "Port": 1433 }
]
}
Оркестратор:
$config = Get-Content "$PSScriptRoot\servers.json" -Raw | ConvertFrom-Json
$report = foreach ($srv in $config.Servers) {
Test-ServerHealth -Server $srv
}
$report | Where-Object { -not $_.Ok } | ForEach-Object { Write-Warning "$($_.Name): $($_.Detail)" }
Классы PowerShell (кратко)
Для стабильной структуры данных в PowerShell 5+ / 7 можно объявить class:
class ServerRecord {
[string]$Name
[string]$HostName
[int]$Port = 443
[bool] TestPort() {
(Test-NetConnection -ComputerName $this.HostName -Port $this.Port -WarningAction SilentlyContinue).TcpTestSucceeded
}
}
$s = [ServerRecord]@{ Name = 'web-01'; HostName = 'web-01.corp.local' }
$s.TestPort()
Классы удобны в модулях с большим числом полей; для простых скриптов достаточно pscustomobject и JSON.
Конфиг внутри модуля
Константы уровня модуля (паттерн из практики работы с SQL через dbatools):
# Inside MyModule.psm1
$_SqlInstance = 'SRV-SQL\SQLEXPRESS'
$_Database = 'PoshAssetMgmt'
function Get-ModuleDatabase {
[CmdletBinding()]
param()
@{ SqlInstance = $_SqlInstance; Database = $_Database }
}
Имена с префиксом $script: или $_ показывают, что это настройки модуля, а не параметры каждого вызова. Для мультисредовых деплоев конфиг модуля генерируют при установке (DSC, Ansible, setup.ps1).
Чего не кладут в конфиг
| Неприемлемо | Альтернатива |
|---|---|
Invoke-Sqlcmd как строка в JSON | Имя функции + switch в коде или отдельные ключи Action: "SqlCheck" |
| Пароль в JSON | SecretName → Get-Secret |
| Произвольный PowerShell в JSON | Расширяемый набор известных действий в коде |
Конфиг описывает что делать; код — как.
Идempotency и повторный запуск
Скрипт идемпотентен, если повторный запуск не ломает состояние: второй раз создаёт тот же результат, а не дубликаты.
Приёмы:
Test-Path/Get-ServiceпередNew-Item/Start-Service;Ensure = 'Present'в DSC — см. 11;- возобновляемость с файлом прогресса — 111.
Конфиг vs база данных
| JSON / YAML | SQL |
|---|---|
| Мало записей, редкие правки, один админ | Много объектов, concurrent update, отчёты |
| Версионирование в Git | Центральный реестр серверов, CMDB |
PowerShell + SQL (модуль dbatools) — для инвентаризации и отчётов; теория SQL — 3.07. Для десятков серверов в JSON хватает; для тысяч — БД или API.
Пример структуры проекта
Deploy-App/
├── Deploy-App.ps1 # оркестратор
├── config.json # пути, флаги (в Git)
├── config.local.json # переопределения (в .gitignore)
└── lib/
└── AppTools.psm1 # функции из [125]
Запуск:
.\Deploy-App.ps1 -ConfigPath .\config.local.json
Чек-лист
| # | Вопрос |
|---|---|
| 1 | Секреты только по имени, не по значению в конфиге? |
| 2 | Конфиг валидируется при старте? |
| 3 | Повторный запуск безопасен (идемпотентность)? |
| 4 | Окружения различаются файлом конфига, а не правкой .ps1? |
| 5 | В JSON нет исполняемого кода? |
Дальше
| Тема | Материал |
|---|---|
| Ошибки, таймауты служб | 12 |
| Azure Automation + конфиг в переменных | 11 |
| Возобновляемые длинные задачи | 111 |
| Pester для конфига | фаза 4 — статья 129 |
См. также
Другие статьи этого же раздела в боковом меню (как на странице "О разделе"). История 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
Типы данных и работа с переменными
Условные выражения и циклы
Функции и продвинутые параметры
Объектная модель и конвейерная обработка