PowerShell 2.0 CTP3: Invoke-Command и первые скрипты на парке серверов
Microsoft выпустила CTP3 PowerShell 2.0 с remoting через WinRM. Написали первые скрипты с Invoke-Command - собираем данные с десятков серверов параллельно.
PowerShell 2.0 CTP3 доступен для тестирования - появились remoting через WinRM и background jobs
На прошлой неделе Microsoft тихо выложила CTP3 PowerShell 2.0. Без большой огласки - просто ссылка в блоге команды и запись в списке рассылки. Мы это дело заметили, поставили на тестовый стенд и потратили два вечера на то, чтобы понять, что за remoting там появился и стоит ли им пользоваться на клиентских площадках.
Короткий ответ: стоит. Хотя это CTP, а не RTM, и пару раз система вела себя неожиданно.
Что изменилось в CTP3
PowerShell 1.0 умел выполнять скрипты локально. Для удалённой работы приходилось городить WMI-запросы, WScript.Network или внешние инструменты вроде PsExec. Каждый вариант - отдельная боль: WMI работает не везде одинаково, PsExec требует прав и оставляет следы в процессах, написать что-то сложнее «перезапусти службу» становилось нетривиально.
В CTP3 появился remoting - по сути, встроенный механизм выполнения команд на удалённых машинах через WinRM (Windows Remote Management, это надстройка над WS-Management). Ключевые инструменты:
Invoke-Command- выполнить scriptblock на одной или нескольких машинах.New-PSSession- открыть постоянную сессию на удалённый хост и работать в ней интерактивно.- Background jobs через
Start-Job/Receive-Job- отправить задачу и забрать результат позже.
Что мы сделали с этим
У одного из клиентов под нашим сопровождением порядка тридцати с лишним Windows-серверов. До этого сбор базовой информации - загрузка процессора за сутки, свободное место на дисках, статус ключевых служб - выглядел так: либо ждёшь, пока Zabbix соберёт, либо идёшь руками через RDP по машинам. Ни то ни другое не удобно, когда клиент просит «дай срез прямо сейчас».
Написали скрипт минут за сорок. Суть простая:
$servers = Get-Content "servers.txt"
$results = Invoke-Command -ComputerName $servers -ScriptBlock {
[PSCustomObject]@{
Host = $env:COMPUTERNAME
CPU_Load = (Get-WmiObject Win32_Processor | Measure-Object -Property LoadPercentage -Average).Average
Disk_C_Free = [math]::Round((Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='C:'" | Select-Object -ExpandProperty FreeSpace) / 1GB, 1)
Uptime_Days = [math]::Round((Get-Date - (gcim Win32_OperatingSystem).LastBootUpTime).TotalDays, 1)
}
}
$results | Sort-Object Host | Format-Table -AutoSize
Invoke-Command сам разбрасывает вызовы по машинам параллельно - не последовательно. Если бы мы обходили список в цикле с WMI напрямую, тридцать серверов с таймаутом по пять секунд - это минуты ожидания. С remoting всё тридцать получают запрос одновременно, результат возвращается по мере ответа.
Где потёрли лоб
WinRM надо включать руками. По умолчанию на Server 2003 и 2008 он выключен. Команда winrm quickconfig запускает службу и открывает нужный порт, но выполнять её на тридцати машинах руками - то ещё приключение. Раскатали через GPO: Computer Configuration - Windows Settings - Security Settings - Windows Firewall, плюс Startup script для winrm quickconfig -q. На всех машинах включилось за следующую ночь.
Firewall и порт 5985. Это HTTP-порт WinRM. На части машин локальный брандмауэр его блокировал. Опять GPO, опять ждать применения. Можно было сделать через winrm quickconfig, но несколько машин за файрволом потребовали ручного вмешательства.
Ошибки не всегда очевидны. Если один из серверов в списке недоступен или WinRM не включён, Invoke-Command выбрасывает ошибку в поток ошибок, но продолжает работать с остальными. Это нормальное поведение, но первые запуски немного смущали - результатов меньше, чем серверов в списке, и не сразу понятно почему. Добавили -ErrorAction SilentlyContinue и отдельно собираем $error в конце.
CTP - это CTP. Пару раз PSSession зависала и не отдавала управление. Пришлось убивать процесс. В production такое неприятно, но на тестовом стенде терпимо.
Что реально сэкономило
Самый очевидный выигрыш - тот самый срез состояния парка. То, что раньше занимало от получаса до часа ручной работы через RDP, теперь готово за полторы минуты. Причём скрипт можно запустить ещё раз через час и получить свежие данные - без открытия новых консолей.
Background jobs оказались полезны в другом сценарии: запускаешь долгую операцию (например, копирование дистрибутива на несколько серверов через Admin$ шары), возвращаешься через время, забираешь статус. Раньше для этого держали открытые RDP-сессии - теперь не нужно.
Мы пока в начале. Скрипт для сбора данных - это первый уровень. Следующий шаг - автоматически запускать определённые действия по результатам: если диск меньше порога, флагировать в журнал; если служба упала и не поднялась, попробовать рестартовать и уведомить. Это уже логика, а не просто сбор. Посмотрим, как поведёт себя инструмент на реальных данных.
- vMotion по всей ферме: первая живая миграция на iSCSI-кластере · 12 февраля 2009
- ESXi без лицензии: переводим сервер с ESX и считаем, что сломалось · 22 января 2009