2.05. Скрипты в среде Windows на PowerShell
Скрипты в среде Windows на PowerShell
Скрипты в Windows — это программы, написанные на языке сценариев и предназначенные для управления операционной системой, её компонентами и приложениями без прямого участия человека. Автоматизация в Windows изначально развивалась через пакетные файлы (.bat, .cmd) и Visual Basic Script (.vbs). Эти технологии выполняли базовые задачи: запуск программ, копирование файлов, управление переменными окружения. Однако их возможности были ограничены: слабая интеграция с системными API, отсутствие строгой типизации, минимальные средства обработки ошибок, трудности в работе с объектами.
PowerShell появился как ответ на вызовы современной ИТ-инфраструктуры — рост числа управляемых узлов, усложнение конфигураций, необходимость централизованного администрирования. Это не просто оболочка, как Command Prompt. PowerShell — это полноценная платформа автоматизации, основанная на .NET Framework (в Windows PowerShell) и .NET Core/.NET 5+ (в PowerShell Core / PowerShell 7+). Она встроена в каждую версию Windows начиная с Windows 7 и Windows Server 2008 R2, и поддерживается на всех современных серверных и клиентских редакциях.
Главное отличие PowerShell от предшественников — его объектная природа. В традиционных текстовых оболочках (например, в Bash) команды обмениваются текстом. Команда ls -l выдаёт строку текста, которую grep парсит по шаблону, cut разрезает на колонки, awk агрегирует числа. Каждый инструмент работает с потоком символов, и программист отвечает за корректность структуры этого потока. В PowerShell команды (cmdlet’ы) передают друг другу объекты — экземпляры классов .NET с именованными свойствами и методами. Когда вы вызываете Get-Process, вы получаете не строки, а массив объектов типа System.Diagnostics.Process. У каждого объекта есть свойства: Id, Name, CPU, WorkingSet; и методы: Kill(), WaitForExit(), Refresh(). Последующие команды (Where-Object, Sort-Object, Select-Object) работают непосредственно со свойствами и методами, не требуя синтаксического разбора текста. Это исключает ошибки в парсинге, повышает надёжность и делает скрипты самодокументируемыми.
Что такое PowerShell
PowerShell — это комбинация из трёх компонентов:
-
Оболочка командной строки (shell) — интерфейс, в который пользователь вводит команды. Это программа
powershell.exe(для Windows PowerShell) илиpwsh.exe(для PowerShell 7+). Она загружает среду выполнения, обрабатывает ввод, выводит результаты, управляет сессией. -
Язык сценариев — декларативный и императивный язык, поддерживающий переменные, условные конструкции, циклы, функции, классы, модули, обработку исключений, потоки и асинхронные операции. Синтаксис заимствован из языков C-семейства, но адаптирован под административные задачи: глагол-существительное в именах команд (
Get-ChildItem,Set-Location,Test-Path), конвейерная передача (|), автоматическое связывание параметров. -
Платформа управления — набор командлетов (cmdlet), провайдеров (provider), модулей и API, позволяющих управлять практически всем в системе: файловой системой, реестром, сетевыми интерфейсами, службами, задачами планировщика, сертификатами, WMI/CIM, Active Directory, Azure, Office 365 и сотнями других компонентов. Большинство командлетов реализованы как .NET-классы, унаследованные от
CmdletилиPSCmdlet. Это позволяет сторонним разработчикам создавать собственные расширения, интегрируя PowerShell в любые системы.
PowerShell поддерживает кроссплатформенную работу: начиная с версии 6.0, он работает не только в Windows, но и в Linux, macOS, даже в контейнерах Docker и на устройствах ARM. Это делает его универсальным инструментом для гибридных и облачных сред.
Файлы скриптов: структура и назначение
Скрипт PowerShell — это текстовый файл с расширением .ps1. Простейший скрипт может содержать одну команду:
Write-Host "Привет, Вселенная IT!"
Более сложный скрипт включает параметры, проверки, циклы, обработку ошибок:
param(
[string]$Path = ".",
[switch]$Recurse
)
if (-not (Test-Path $Path)) {
Write-Error "Путь '$Path' не существует."
exit 1
}
$files = Get-ChildItem -Path $Path -File -Recurse:$Recurse
Write-Host "Найдено $($files.Count) файлов."
$files | ForEach-Object {
Write-Host " $($_.Name) — $($_.Length) байт"
}
Такой файл сохраняется как List-Files.ps1. Его содержимое — это программа, которую PowerShell интерпретирует построчно (или компилирует в памяти для повышения производительности). Скрипт может быть запущен многократно, с разными параметрами, в разных контекстах.
Кроме .ps1, в экосистеме PowerShell используются:
-
.psm1— файлы модулей. Модуль — это набор функций, переменных, классов, объединённых логически (например, модуль для работы с реестром, модуль для администрирования Exchange Server). Модуль загружается командойImport-Module. -
.psd1— файлы манифеста модуля. Это данные в формате хэш-таблицы PowerShell, описывающие модуль: его версию, автора, зависимости, экспортируемые функции, требуемые разрешения. -
.ps1xml— файлы форматирования и типов. Они определяют, как объекты отображаются в консоли (столбцы, ширина, цвета), какие методы и свойства доступны по умолчанию.
Эти расширения не требуют дополнительной настройки — PowerShell распознаёт их по имени и применяет соответствующие правила обработки.
Политика выполнения: механизм доверия
PowerShell включает встроенную систему безопасности, называемую политикой выполнения (Execution Policy). Эта политика не является средством защиты от вредоносного ПО, а скорее инструментом предотвращения случайного запуска непроверенного кода. По умолчанию на клиентских системах (Windows 10/11) установлена политика Restricted. Она блокирует выполнение всех скриптов, включая локальные, и разрешает только интерактивный ввод команд в консоли.
Другие распространённые политики:
-
AllSigned— разрешает выполнение только тех скриптов, которые подписаны цифровой подписью доверенного издателя. Это используется в строго контролируемых корпоративных средах. -
RemoteSigned— разрешает запуск локальных скриптов без подписи, но требует подписи для скриптов, скачанных из интернета (например, через браузер или почту). Эта политика считается оптимальной для большинства пользователей. -
Unrestricted— разрешает запуск всех скриптов, но перед выполнением скачанного скрипта выводит предупреждение. Подходит для изолированных сред разработки и тестирования. -
Bypass— отключает все проверки. Используется в автоматизированных системах, где скрипты запускаются без участия человека.
Политику можно проверить командой:
Get-ExecutionPolicy
Изменить — командой Set-ExecutionPolicy. Изменение требует прав администратора, если применяется на уровне машины (-Scope LocalMachine). Для текущего пользователя достаточно обычных прав:
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
Важно: политика выполнения хранится в реестре и применяется на этапе запуска сессии PowerShell. Она не влияет на выполнение команд, введённых вручную, и не блокирует вызов .NET-методов напрямую.
Запуск скриптов: способы и контексты
Скрипт можно запустить несколькими способами, каждый со своими особенностями.
1. Запуск из консоли PowerShell
Откройте PowerShell (через «Пуск» → «Windows PowerShell» или поиск). Перейдите в каталог со скриптом:
cd C:\Scripts
Выполните скрипт с помощью оператора вызова (&) или точечной нотации (dot-sourcing):
-
.\MyScript.ps1— запускает скрипт в дочерней области видимости. Переменные, созданные внутри скрипта, не попадают в текущую сессию после завершения. Это стандартный и безопасный способ. -
. .\MyScript.ps1— dot-source — загружает скрипт в текущую область видимости. Функции и переменные остаются доступны после завершения. Используется для загрузки профилей, библиотек функций, настройки окружения.
2. Запуск из командной строки (cmd.exe) или ярлыка
Можно вызвать PowerShell из любого места системы, передав путь к скрипту:
powershell.exe -File "C:\Scripts\MyScript.ps1"
Ключ -File гарантирует, что аргумент интерпретируется как путь к файлу, даже если имя содержит пробелы или специальные символы. Альтернатива — -Command, но она требует экранирования и менее надёжна для сложных скриптов.
Этот способ используется в ярлыках, планировщике задач, групповых политиках и системных службах.
3. Запуск через контекстное меню
Если щёлкнуть правой кнопкой по файлу .ps1 в Проводнике, в меню появится пункт «Выполнить с помощью PowerShell». Эта команда запускает скрипт в новом окне консоли с политикой, установленной по умолчанию. Окно остаётся открытым после завершения — это позволяет увидеть результаты и ошибки. Для автоматических задач такой способ не подходит, но он удобен при тестировании.
4. Запуск через PowerShell ISE или VS Code
Интегрированные среды предоставляют кнопки «Запустить», «Запустить выделенное», «Отладка». Запуск происходит в рамках текущей сессии, что позволяет пошагово выполнять код, просматривать значения переменных, ставить точки останова.
Сравнение PowerShell и Bash: две философии автоматизации
PowerShell и Bash — это не просто две разные командные оболочки. Это выражение двух различных подходов к управлению вычислительной средой: один — ориентированный на объекты и строгую типизацию, другой — на текст и композицию утилит.
Исторический контекст
Bash (Bourne-Again Shell) развивалась в среде Unix и Linux, где доминировала идея «всё есть файл». Даже устройства, процессы и сетевые сокеты представлены как файлы в виртуальной файловой системе. Это позволило создать утилиты, которые читают из stdin, пишут в stdout, и комбинируются через конвейер (|). Каждая утилита решает одну задачу, делает это хорошо, и передаёт результат — текст — следующей. Так родились grep, sed, awk, cut, sort, uniq. Эта модель чрезвычайно гибкая, но требует от пользователя знания синтаксиса регулярных выражений, экранирования и формата вывода каждой утилиты.
PowerShell появился позже, в 2006 году, в среде Windows, где API системных компонентов строились на COM и .NET — объектно-ориентированных технологиях. Разработчики PowerShell осознанно отказались от текстового конвейера в пользу объектного. Цель — сделать автоматизацию доступной для администраторов без глубоких знаний программирования, сохраняя при этом мощь и выразительность.
Конвейер: текст против объектов
В Bash команда:
ps aux | grep nginx | awk '{print $2, $11}'
— сначала порождает текстовый вывод ps, затем grep фильтрует строки, содержащие «nginx», затем awk разбирает каждую строку по пробелам и выбирает второе и одиннадцатое поле. Если формат вывода ps изменится (например, добавится колонка с GPU-нагрузкой), скрипт сломается. Если имя процесса содержит пробелы, awk сдвинет индексы. Это хрупкая конструкция.
В PowerShell аналогичная задача:
Get-Process -Name nginx | Select-Object Id, Path
— получает массив объектов Process, фильтрует по свойству Name, затем выбирает два свойства: Id (идентификатор процесса) и Path (полный путь к исполняемому файлу). Формат объекта не зависит от способа отображения. Даже если Microsoft изменит текстовый вывод Get-Process, объекты останутся теми же. Свойства Id и Path — часть контракта API, и их изменение потребует критического обновления системы, что маловероятно.
Объектный конвейер исключает необходимость в grep/awk для базовой фильтрации и выборки. Вместо них используются универсальные командлеты:
Where-Object— фильтрация по условию ({ $_.CPU -gt 50 })Sort-Object— сортировка по свойствам (-Property CPU -Descending)Group-Object— группировка (-Property Company)Measure-Object— агрегация (-Property WS -Sum -Average)ForEach-Object— применение кода к каждому элементу ({ $_.Kill() })
Эти командлеты работают с любыми объектами, а не только с процессами. Это обеспечивает единообразие: один и тот же синтаксис применим к файлам, службам, сетевым адаптерам, сертификатам.
Синтаксис и читаемость
Bash использует компактный, насыщенный символами синтаксис:
$?— код возврата последней команды$$— PID текущего процесса$!— PID последнего фонового процесса&>— перенаправление stdout и stderr[[ ]]— расширенное условие$( )— подстановка команды
Этот стиль экономит символы, но повышает порог входа. PowerShell выбирает многословность и самодокументируемость:
$LASTEXITCODE— понятное имя переменной$PID— идентификатор процессаStart-Process -NoNewWindow— параметры в именованной формеif ($result -eq $true)— читаемое условие& { Get-Date }— явный вызов скрипт-блока
Имена командлетов следуют схеме Глагол-Существительное (Get-Service, Stop-Process, New-Item, Test-Connection). Это позволяет угадывать команду по её назначению и легко находить её через Get-Command -Verb Stop или Get-Help *service*.
Ошибки и отладка
Bash по умолчанию не прерывает выполнение при ошибке. Скрипт продолжает работать, даже если команда завершилась с кодом 1. Это требует явной проверки $? после каждой критической операции. PowerShell по умолчанию использует останавливающие ошибки (terminating errors) для большинства командлетов. Если Get-ChildItem не находит путь, он генерирует исключение. Это принуждает к осознанной обработке сбоев.
PowerShell поддерживает полноценную обработку исключений:
try {
$content = Get-Content -Path "C:\secret.txt" -ErrorAction Stop
Write-Host "Файл прочитан."
}
catch [System.UnauthorizedAccessException] {
Write-Warning "Нет прав на чтение файла."
}
catch {
Write-Error "Неизвестная ошибка: $($_.Exception.Message)"
}
finally {
Write-Host "Операция завершена."
}
Конструкция try/catch/finally работает как в C# или Java. Это делает код предсказуемым и устойчивым к внештатным ситуациям.
Провайдеры: единый интерфейс к разным хранилищам
Bash работает преимущественно с файловой системой. Доступ к реестру, сертификатам или переменным окружения требует специальных утилит (reg, certutil, printenv) или встроенных команд (declare, export).
PowerShell вводит концепцию провайдеров (providers). Провайдер — это адаптер, который отображает произвольное хранилище данных в иерархию, похожую на файловую систему. Встроенные провайдеры:
FileSystem— диски, папки, файлыRegistry— разделы и параметры реестра Windows (HKLM:\SOFTWARE)Environment— переменные окружения (Env:\PATH)Certificate— сертификаты (Cert:\CurrentUser\My)Alias— псевдонимы команд (Alias:\cd)Variable— переменные сессии (Variable:\PWD)Function— определённые функции (Function:\Write-Host)
Команды Get-ChildItem, Get-Item, Set-Item, New-Item, Remove-Item работают со всеми провайдерами одинаково:
# Просмотр переменных
Get-ChildItem Env:
# Чтение параметра реестра
(Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager").BootExecute
# Добавление переменной окружения
New-Item -Path Env:\MY_APP_CONFIG -Value "Production"
# Удаление сертификата
Remove-Item -Path "Cert:\LocalMachine\My\$thumbprint"
Это создаёт единый язык управления разнородными данными.
Интегрированная среда сценариев (ISE): графическая оболочка для разработки
Windows PowerShell ISE — это официальная графическая среда разработки скриптов, поставляемая вместе с Windows. Она включает три основные области:
-
Панель меню и панель инструментов — кнопки «Создать», «Открыть», «Сохранить», «Запустить», «Остановить», «Выполнить выделенное». Каждая операция имеет горячие клавиши (например, F5 — запуск всего скрипта, F8 — выполнение выделенного фрагмента).
-
Область сценариев — редактор кода с подсветкой синтаксиса, автоформатированием, сворачиванием блоков (
#region/#endregion), навигацией по ошибкам. Поддерживается поиск и замена по регулярным выражениям, переход к строке по номеру (Ctrl+G), отмена и повтор действий (Ctrl+Z, Ctrl+Y). -
Область консоли — интерактивная сессия PowerShell. В отличие от отдельного окна консоли, здесь можно комбинировать выполнение скриптов и ручной ввод. Например, запустить скрипт, затем вызвать функцию из него, проверить значение переменной, изменить её и повторно вызвать функцию — всё в одном окне.
Отладка: пошаговое выполнение
ISE предоставляет полноценный отладчик:
- Точки останова ставятся кликом слева от номера строки или через меню. Можно задать условие (
$i -gt 10) или действие при остановке (вывести значение переменной). - Шаг с заходом (F11) — заходит внутрь функции.
- Шаг с обходом (F10) — выполняет функцию целиком, не заходя внутрь.
- Выполнение до курсора (Ctrl+F10) — запускает код до указанной строки.
- Панель локальных переменных — отображает все переменные в текущей области видимости, их тип и значение. Можно изменить значение прямо в таблице.
- Панель стека вызовов — показывает цепочку вызовов функций, позволяя «подняться» на уровень выше.
Это позволяет анализировать состояние программы в реальном времени, выявлять логические ошибки, проверять граничные условия.
Работа с профилями и модулями
ISE автоматически загружает пользовательский профиль при запуске. Профиль — это скрипт Microsoft.PowerShellISE_profile.ps1, расположенный в папке Documents\WindowsPowerShell. В нём можно:
- Задать псевдонимы (
Set-Alias ll Get-ChildItem) - Определить вспомогательные функции (
function prompt { "PS> " }) - Настроить цветовую схему (
$psISE.Options.ConsoleTokenColors['String'] = 'DarkGreen') - Импортировать часто используемые модули (
Import-Module ActiveDirectory)
ISE также поддерживает работу с модулями. Можно открыть .psm1-файл, внести изменения, нажать F5 — и модуль перезагрузится в текущей сессии. Это ускоряет цикл «написать — проверить — доработать».
Примечание: Начиная с Windows 10 версии 1903, Microsoft объявила ISE устаревшей и рекомендует использовать Visual Studio Code с расширением PowerShell. Однако ISE остаётся в системе по совместимости и удобна для быстрого запуска и отладки без установки дополнительных инструментов.
Структура скрипта: от идеи к надёжной программе
Простой одноразовый скрипт — это последовательность команд. Профессиональный скрипт — это программная единица, которая:
- принимает параметры
- содержит документацию
- проверяет входные данные
- обрабатывает ошибки
- логирует действия
- возвращает результат
Параметры: гибкость через декларацию
В начале скрипта объявляется блок param(). Он определяет, какие аргументы может принимать скрипт, их тип, значение по умолчанию, обязательность:
param(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$ComputerName,
[int]$Port = 80,
[ValidateSet("HTTP", "HTTPS")]
[string]$Protocol = "HTTP",
[switch]$Verbose
)
[Parameter(Mandatory = $true)]требует обязательного указания параметра.[ValidateNotNullOrEmpty()]проверяет, что строка не пустая и не null.[ValidateSet(...)]ограничивает значения списком.[switch]— это булев флаг, который активируется, если указан (например,-Verbose).
Параметры можно передавать:
- По имени:
.\Test-Connection.ps1 -ComputerName srv01 -Port 443 - Позиционно:
.\Test-Connection.ps1 srv01 443(если порядок соблюдён) - Через хэш-таблицу (splatting):
$params = @{ ComputerName = "srv01"; Port = 443; Verbose = $true }
.\Test-Connection.ps1 @params
Splatting особенно удобен при вызове командлетов с множеством параметров.
Документация: комментарии, которые читает система
PowerShell поддерживает стандарт комментариев на основе XML — комментарии помощи (comment-based help). Они размещаются в начале скрипта или функции и описываются так:
<#
.SYNOPSIS
Проверяет доступность веб-сервера.
.DESCRIPTION
Отправляет HTTP-запрос на указанный хост и порт, возвращает код ответа.
.PARAMETER ComputerName
Имя или IP-адрес сервера.
.PARAMETER Port
Порт (по умолчанию — 80).
.EXAMPLE
Test-WebServer -ComputerName example.com -Port 443
#>
После этого команда Get-Help .\Test-WebServer.ps1 выводит отформатированное описание, как для встроенных командлетов. Это делает скрипты самодокументируемыми и интегрируемыми в обучающие материалы.
Обработка ошибок: контроль над сбоями
В скриптах используются три уровня обработки:
-
Предварительная проверка —
Test-Path,Test-Connection,Test-ModuleManifest. Эти командлеты возвращают$true/$falseбез исключений. -
Управляемые исключения —
try/catch, как показано выше. -
Глобальные настройки — параметр
-ErrorActionу каждой команды:Stop— превращает неостанавливающую ошибку в исключение.Continue— выводит ошибку, но продолжает выполнение (по умолчанию).SilentlyContinue— подавляет вывод ошибки.Ignore— подавляет ошибку и не записывает её в$Error.
Пример надёжного чтения файла:
$content = Get-Content -Path $Path -ErrorAction SilentlyContinue
if (-not $content) {
Write-Warning "Файл '$Path' пуст или недоступен."
return
}
Такой подход позволяет избежать аварийного завершения и дать пользователю осмысленную обратную связь.
Распространённые задачи: скрипты как инструмент повседневной работы
Скрипты PowerShell находят применение в десятках сценариев. Ниже — разбор типичных задач с пояснением логики, структуры и масштабируемости решений. Каждый пример можно использовать как шаблон и адаптировать под свои нужды.
1. Резервное копирование файлов и папок
Резервное копирование — одна из самых частых задач. Простой скрипт копирует папку с отметкой времени в имени архива:
param(
[string]$SourcePath = "C:\Projects",
[string]$BackupRoot = "D:\Backups"
)
$timestamp = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
$backupName = "Backup_$timestamp.zip"
$backupPath = Join-Path -Path $BackupRoot -ChildPath $backupName
# Создаём папку для бэкапов, если её нет
if (-not (Test-Path $BackupRoot)) {
New-Item -Path $BackupRoot -ItemType Directory -Force
}
# Используем встроенный .NET-метод для архивации
Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::CreateFromDirectory($SourcePath, $backupPath)
Write-Host "Резервная копия создана: $backupPath"
Этот скрипт:
- принимает параметры
SourcePathиBackupRoot, задаёт значения по умолчанию; - генерирует уникальное имя с точной датой и временем;
- проверяет существование целевой папки и создаёт её при необходимости;
- использует класс
ZipFileиз .NET — это надёжнее вызова внешних утилит вроде7z.exe; - выводит подтверждение.
Его можно расширить:
- добавить проверку свободного места на диске (
Get-PSDrive D | Select-Object Free); - включить сжатие с уровнем (
CompressionLevel::Optimal); - отправить уведомление по электронной почте (
Send-MailMessage); - удалить старые копии старше 30 дней (
Get-ChildItem -Path $BackupRoot -Filter *.zip | Where-Object { $_.CreationTime -lt (Get-Date).AddDays(-30) } | Remove-Item).
Такой скрипт легко интегрируется в Планировщик заданий Windows — ежедневное, еженедельное или по триггеру (например, после завершения сборки проекта).
2. Управление правами доступа (ACL)
В Windows права доступа к файлам и папкам задаются через списки контроля доступа (ACL). Их настройка вручную — трудоёмкий процесс. Скрипт позволяет массово изменить права:
param(
[string]$Path = "C:\Shared",
[string]$User = "DOMAIN\Developers",
[string[]]$Permissions = @("ReadAndExecute", "Write")
)
$acl = Get-Acl -Path $Path
# Создаём правило доступа
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
$User,
$Permissions -join ",",
"ContainerInherit,ObjectInherit",
"None",
"Allow"
)
# Добавляем правило в ACL
$acl.SetAccessRule($accessRule)
# Применяем обновлённый ACL
Set-Acl -Path $Path -AclObject $acl
Write-Host "Права для '$User' назначены на '$Path'."
Скрипт:
- получает текущий ACL через
Get-Acl; - создаёт объект
FileSystemAccessRuleс указанием пользователя, прав (Read,Write,FullControlи др.), наследования и типа (разрешение/запрет); - добавляет правило в ACL;
- применяет изменения.
Важные детали:
"ContainerInherit,ObjectInherit"означает, что права распространяются на подпапки и файлы.- Можно заменить
SetAccessRuleнаAddAccessRule, если нужно добавить правило, не затирая существующие. - Для удаления прав используется
RemoveAccessRule.
Такой подход исключает ошибки при ручной настройке и гарантирует единообразие политик безопасности.
3. Мониторинг использования ресурсов
Скрипт может отслеживать нагрузку на компьютер и реагировать на отклонения:
param(
[int]$CpuThreshold = 90,
[int]$MemoryThreshold = 85,
[int]$CheckIntervalSeconds = 60
)
while ($true) {
$cpu = (Get-Counter '\Processor(_Total)\% Processor Time').CounterSamples.CookedValue
$mem = (Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory /
(Get-CimInstance Win32_OperatingSystem).TotalVisibleMemorySize * 100
$freeMemPercent = 100 - $mem
Write-Host "[$(Get-Date -Format 'HH:mm:ss')] CPU: $([int]$cpu)% | Память: $([int]$freeMemPercent)% свободно"
if ($cpu -gt $CpuThreshold) {
Write-Warning "Высокая загрузка CPU: $([int]$cpu)%"
Get-Process | Sort-Object CPU -Descending | Select-Object -First 5 | Format-Table Id, Name, CPU
}
if ($freeMemPercent -lt (100 - $MemoryThreshold)) {
Write-Warning "Низкий уровень свободной памяти: $([int]$freeMemPercent)%"
}
Start-Sleep -Seconds $CheckIntervalSeconds
}
Этот скрипт:
- использует
Get-Counterдля получения точных данных счётчиков производительности (в отличие от приблизительных значений в диспетчере задач); - вычисляет процент свободной памяти на основе CIM-модели;
- выводит текущую статистику с отметкой времени;
- при превышении порогов — показывает топ-5 процессов по CPU;
- работает в бесконечном цикле с паузой через
Start-Sleep.
Его можно доработать:
- записывать лог в файл (
Out-File -Append); - отправлять оповещение в Telegram через
Invoke-RestMethod; - автоматически завершать «прожорливые» процессы по правилам.
4. Массовая установка программ через Chocolatey
Chocolatey — менеджер пакетов для Windows. Скрипт позволяет развернуть стандартный набор ПО на новом компьютере:
# Установка Chocolatey (если отсутствует)
if (-not (Get-Command choco -ErrorAction SilentlyContinue)) {
Set-ExecutionPolicy Bypass -Scope Process -Force
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
}
$packages = @(
"googlechrome",
"firefox",
"vscode",
"7zip",
"git",
"nodejs",
"python3",
"docker-desktop"
)
foreach ($pkg in $packages) {
Write-Host "Устанавливаю $pkg..."
choco install $pkg -y --no-progress
}
Скрипт:
- проверяет наличие
choco; - при необходимости устанавливает его с правильным протоколом безопасности;
- перебирает список пакетов и устанавливает их без подтверждения (
-y); - отключает прогресс-бар для автоматизации.
Это решение ускоряет подготовку рабочих станций в корпоративной среде, обеспечивает единообразие версий и исключает «ручной» поиск установщиков.
Модули и реиспользуемость кода
Один и тот же код не должен дублироваться в десятках скриптов. PowerShell предлагает механизм модулей — логических единиц, объединяющих связанные функции, переменные, классы и данные.
Структура модуля
Модуль — это папка с именем MyTools, содержащая как минимум один файл .psm1:
MyTools/
├── MyTools.psd1 # манифест (опционально, но рекомендуется)
└── MyTools.psm1 # основной код
Файл .psm1 содержит функции:
# MyTools.psm1
function Get-FreeSpace {
param([string]$Drive = "C")
$info = Get-PSDrive $Drive
[PSCustomObject]@{
Drive = $Drive
FreeGB = [math]::Round($info.Free / 1GB, 2)
UsedGB = [math]::Round($info.Used / 1GB, 2)
TotalGB = [math]::Round(($info.Free + $info.Used) / 1GB, 2)
}
}
function Test-Url {
param([string]$Url)
try {
$request = Invoke-WebRequest -Uri $Url -Method Head -TimeoutSec 10
$request.StatusCode -eq 200
} catch {
$false
}
}
Export-ModuleMember -Function Get-FreeSpace, Test-Url
Export-ModuleMemberуказывает, какие функции будут доступны после импорта модуля.- Внутри модуля можно определять приватные вспомогательные функции — они не будут экспортированы.
Использование модуля
-
Поместите папку
MyToolsв одну из стандартных директорий модулей:- Для текущего пользователя:
~\Documents\PowerShell\Modules\ - Для всех пользователей:
$env:ProgramFiles\PowerShell\Modules\
- Для текущего пользователя:
-
Импортируйте модуль:
Import-Module MyTools -
Используйте функции:
Get-FreeSpace -Drive D
Test-Url "https://spirzen.ru"
Преимущества модулей
- Инкапсуляция — внутренняя логика скрыта, интерфейс чётко определён.
- Версионность — в
.psd1можно указатьModuleVersion = '1.2.0', что позволяет управлять обновлениями. - Зависимости — модуль может требовать другие модули (
RequiredModules = @('ActiveDirectory')). - Автозагрузка — начиная с PowerShell 3.0, модули загружаются автоматически при вызове экспортируемой функции.
Модули — основа для построения библиотек внутренних инструментов в крупных организациях. Например, модуль ADTools для работы с Active Directory, BackupSystem для управления архивами, ReportGenerator для формирования отчётов в Excel или PDF.
Лучшие практики написания скриптов
Качественный скрипт — это не только рабочий код. Это документ, который другие могут читать, поддерживать и расширять.
1. Именование
- Файлы скриптов и модулей — в стиле PascalCase:
Backup-Database.ps1,NetworkTools.psm1. - Функции — Глагол-Существительное, согласно утверждённому списку глаголов:
Get-LogEntry,Set-Configuration,Test-Connection. - Переменные — camelCase:
$inputPath,$userList,$maxRetries.
2. Безопасность
- Избегайте
Set-ExecutionPolicy Unrestrictedв продакшене. ИспользуйтеRemoteSignedили цифровую подпись. - Не храните пароли в открытом виде. Используйте
Get-Credential,ConvertFrom-SecureString, или менеджеры секретов (Azure Key Vault, HashiCorp Vault). - Запускайте скрипты с минимально необходимыми правами. Для административных задач — отдельная учётная запись.
3. Тестирование
PowerShell имеет встроенную систему тестирования — Pester. Пример теста:
# Backup-Database.Tests.ps1
Describe "Backup-Database" {
It "Создаёт ZIP-файл в указанной папке" {
$backupPath = "TestDrive:\backup.zip"
Backup-Database -Source "TestDrive:\data" -Destination $backupPath
$backupPath | Should -Exist
(Get-Item $backupPath).Length | Should -BeGreaterThan 0
}
}
Pester позволяет писать unit-тесты, интеграционные тесты, проверять исключения, параметры, выходные объекты. Это гарантирует, что изменения не ломают существующую функциональность.
4. Логирование
Всегда записывайте ключевые этапы выполнения:
$LogPath = "C:\Logs\Backup_$(Get-Date -Format 'yyyyMMdd').log"
Start-Transcript -Path $LogPath -Append
# ... основной код ...
Stop-Transcript
Или используйте Write-Information, Write-Verbose, Write-Debug с параметром -InformationAction Continue. Это позволяет включать/выключать уровни детализации без изменения кода.
Современные инструменты: PowerShell в Windows Terminal и VS Code
Хотя ISE остаётся в системе, новые проекты лучше разрабатывать в современных средах.
Windows Terminal
Это центральный терминал для Windows 10/11. Он поддерживает вкладки, профили, настраиваемые шрифты (включая Nerd Fonts), темы, прозрачность, анимации курсора. PowerShell автоматически становится одним из профилей:
- Откройте Windows Terminal.
- Нажмите стрелку вниз → «Настройки».
- В
settings.jsonможно добавить кастомную команду, переменные окружения, начальную директорию.
Пример профиля для PowerShell 7:
{
"guid": "{574e775e-4f2a-5b96-ac1e-a2962a402336}",
"name": "PowerShell 7",
"commandline": "pwsh.exe",
"hidden": false,
"colorScheme": "One Half Dark"
}
Visual Studio Code + расширение PowerShell
VS Code — рекомендуемая Microsoft среда для PowerShell-разработки. После установки расширения PowerShell появляются:
- Интеллектуальное завершение кода (IntelliSense) с подсказками по параметрам.
- Отладчик с точками останова, просмотром переменных, стеком вызовов.
- Встроенный терминал с поддержкой нескольких сессий.
- Анализ кода (PSScriptAnalyzer) — выявляет стилевые и потенциальные ошибки.
- Поддержка Jupyter-ноутбуков (
.ipynb) с ячейками PowerShell.
Преимущества VS Code:
- Кроссплатформенность — один и тот же интерфейс на Windows, Linux, macOS.
- Интеграция с Git — просмотр изменений, коммиты, ветвление прямо в редакторе.
- Поддержка Remote-SSH — написание скриптов для Linux-серверов с той же средой.