Скрипт powershell как служба
about_Scripts
Краткое описание
Описание запуска и записи скриптов в PowerShell.
Подробное описание
Выполнение сценария во многом похоже на выполнение командлета. Введите путь и имя файла скрипта и используйте параметры для отправки данных и задания параметров. Сценарии можно запускать на компьютере или в удаленном сеансе на другом компьютере.
Написание сценария сохраняет команду для последующего использования и упрощает совместное использование с другими пользователями. Что самое важное, это позволяет выполнять команды просто путем ввода пути скрипта и имени файла. Скрипты могут быть простыми как одной командой в файле, так и сложной программой.
Сценарии имеют дополнительные функции, такие как #Requires Специальный комментарий, использование параметров, поддержка разделов данных и цифровая подпись для обеспечения безопасности. Также можно написать разделы справки для скриптов и для любых функций в скрипте.
Выполнение сценария
перед запуском скрипта на Windows необходимо изменить политику выполнения PowerShell по умолчанию. политика выполнения не применяется к PowerShell, работающему на платформах, отличных от Windows.
Политика выполнения по умолчанию Restricted предотвращает выполнение всех скриптов, включая скрипты, которые вы пишете на локальном компьютере. Подробнее см. в разделе about_Execution_Policies.
Политика выполнения сохраняется в реестре, поэтому ее необходимо изменить только один раз на каждом компьютере.
Чтобы изменить политику выполнения, используйте следующую процедуру.
В командной строке введите:
Изменение вступает в силу немедленно.
Чтобы выполнить сценарий, введите полное имя файла скрипта и полный путь к нему.
Например, чтобы запустить сценарий Get-ServiceLog.ps1 в каталоге C:\Scripts, введите:
Например, чтобы запустить сценарий ServicesLog.ps1 в локальном каталоге, введите:
Если у скрипта есть параметры, введите параметры и значения параметров после имени файла скрипта.
Например, следующая команда использует параметр ServiceName скрипта Get-ServiceLog, чтобы запросить журнал действия службы удаленного управления Windows.
В качестве функции безопасности PowerShell не выполняет сценарии при двойном щелчке значка скрипта в проводнике или при вводе имени сценария без полного пути, даже если сценарий находится в текущем каталоге. Дополнительные сведения о выполнении команд и сценариев в PowerShell см. в разделе about_Command_Precedence.
Запуск с помощью PowerShell
Начиная с PowerShell 3,0 можно запускать сценарии из проводника.
Чтобы использовать функцию «Запуск с помощью PowerShell», сделайте следующее:
Запустите проводник, щелкните правой кнопкой мыши имя файла скрипта и выберите команду «запустить с помощью PowerShell».
Функция «запустить с помощью PowerShell» предназначена для выполнения скриптов, которые не имеют обязательных параметров и не возвращают выходные данные в командную строку.
Дополнительные сведения см. в разделе about_Run_With_PowerShell.
Выполнение сценариев на других компьютерах
Чтобы запустить сценарий на одном или нескольких удаленных компьютерах, используйте параметр FilePath Invoke-Command командлета.
Следующая команда запускает Get-ServiceLog.ps1 сценарий на удаленных компьютерах с именем Server01 и Server02.
Получить справку по сценариям
Командлет Get-Help получает разделы справки для скриптов, а также для командлетов и других типов команд. Чтобы получить раздел справки для скрипта, введите, Get-Help за которым следует путь и имя файла скрипта. Если путь к скрипту находится в Path переменной среды, путь можно опустить.
Например, чтобы получить справку по сценарию ServicesLog.ps1, введите:
Написание сценария
Скрипт может содержать любые допустимые команды PowerShell, в том числе отдельные команды, команды, использующие конвейер, функции и управляющие структуры, такие как операторы If и циклы for.
Следующий пример представляет собой простой сценарий, который получает службы, работающие в текущей системе, и сохраняет их в файл журнала. Имя файла журнала создается с текущей даты.
Параметры в скриптах
Чтобы определить параметры в скрипте, используйте инструкцию param. Param Инструкция должна быть первой инструкцией в скрипте, за исключением комментариев и любых #Require инструкций.
Параметры сценария работают как параметры функции. Значения параметров доступны для всех команд в скрипте. Все функции параметров функций, включая атрибут Parameter и его именованные аргументы, также допустимы в скриптах.
При выполнении скрипта пользователи заменяют параметры после имени скрипта.
Чтобы выполнить этот скрипт, введите имя параметра после имени скрипта. Пример:
Дополнительные сведения о инструкции Param и параметрах функции см. в разделе about_Functions и about_Functions_Advanced_Parameters.
Написание справки для сценариев
Раздел справки для скрипта можно написать с помощью любого из двух следующих методов.
Comment-Based справки по сценариям
Создайте раздел справки, используя специальные ключевые слова в комментариях. Чтобы создать справку на основе комментариев для сценария, необходимо поместить комментарии в начало или в конец файла скрипта. Дополнительные сведения о справке на основе комментариев см. в разделе about_Comment_Based_Help.
XML-Based справки по сценариям
Создайте раздел справки на основе XML, например тип, который обычно создается для командлетов. При преобразовании разделов справки на несколько языков требуется справка на основе XML.
Чтобы связать скрипт с разделом справки на основе XML, используйте. Ключевое слово комментария справки Екстерналхелп. Дополнительные сведения о ключевом слове Екстерналхелп см. в разделе about_Comment_Based_Help. Дополнительные сведения о справке на основе XML см. в разделе как написать справку по командлетам.
Возврат значения выхода
Область скрипта и источники с точкой
Каждый скрипт выполняется в отдельной области. Функции, переменные, псевдонимы и диски, созданные в сценарии, существуют только в области скрипта. Доступ к этим элементам или их значениям в области, в которой выполняется скрипт, невозможен.
Чтобы выполнить скрипт в другой области, можно указать область, например Global или local, или создать точку для скрипта.
Функция «с точкой» позволяет запускать скрипт в текущей области, а не в области скрипта. При запуске скрипта, который имеет точку с точкой, команды в скрипте выполняются так, будто были введены в командной строке. Функции, переменные, псевдонимы и диски, создаваемые сценарием, создаются в области, в которой выполняется работа. После выполнения скрипта можно использовать созданные элементы и получить доступ к их значениям в сеансе.
Чтобы создать точку скрипта для исходного кода, введите точку (.) и пробел перед путем к сценарию.
или диспетчер конфигурации служб
После UtilityFunctions.ps1 выполнения скрипта функции и переменные, создаваемые сценарием, добавляются в текущую область.
Дополнительные сведения об области действия см. в разделе about_Scopes.
Скрипты в модулях
Модуль — это набор связанных ресурсов PowerShell, которые можно распространять как единое целое. Вы можете использовать модули для организации скриптов, функций и других ресурсов. Можно также использовать модули для распространения кода среди других пользователей и получения кода из надежных источников.
Можно включить скрипты в модули или создать модуль скрипта, который представляет собой модуль, полностью или в основном содержащий скрипт и вспомогательные ресурсы. Модуль скрипта — это просто сценарий с расширением файла PSM1.
Дополнительные сведения о модулях см. в разделе about_Modules.
Другие функции сценариев
В PowerShell есть много полезных функций, которые можно использовать в скриптах.
#Requires — Можно использовать #Requires инструкцию, чтобы предотвратить выполнение скрипта без указанных модулей или оснасток и заданную версию PowerShell. Дополнительные сведения см. в разделе about_Requires.
$PSCommandPath — Содержит полный путь и имя выполняемого скрипта. Этот параметр допустим во всех скриптах. Эта автоматическая переменная появилась в PowerShell 3,0.
Пскоммандпас содержит полный путь и имя скрипта, который вызывал или вызывает текущий скрипт.
PSScriptRoot содержит каталог скрипта, вызвавшего или вызвавшего текущий скрипт.
Разделы данных. Вы можете использовать Data ключевое слово для разделения данных из логики в скриптах. Разделы данных также могут упростить локализацию. Дополнительные сведения см. в разделе about_Data_Sections и about_Script_Internationalization.
Подпись скрипта. Вы можете добавить цифровую подпись к сценарию. В зависимости от политики выполнения можно использовать цифровые подписи для ограничения выполнения скриптов, которые могут включать ненадежные команды. Дополнительные сведения см. в разделе about_Execution_Policies и about_Signing.
Запуск PowerShell скрипта как службы Windows
Из любого скрипта PowerShell можно сделать службу Windows, которая работает в фоновом режиме и запускается автоматически при загрузке сервера. Вы можете создать службу Windows с помощью утилит srvany.exe и instsrv.exe (из состава Windows Server Resource 2003 Kit), позволяющих запустить процесс powershell.exe с параметром в виде пути к ps1 файлу скрипта. Основной недостаток такого способа создания службы — srvany.exe не контролирует выполнение приложения (скрипта PowerShell в нашем случае) и, если приложение падает (зависает), то служба это не видит и продолжает работать. В этой статье для создания службы Windows из файла со скриптом PowerShell мы будем использовать утилиту NSSM (Non-Sucking Service Manager – оставим без перевода…:)), которая лишена этих недостатков.
Вы можете скачать и установить NSSM вручную или через Chocolately. Сначала нужно разрешить запуск PS1 скриптов в сесиии и установить сам Choco:
Затем установим пакет NSSM:
choco install nssm
В этом примере мы будем в реальном времени отслеживать изменения определенной группы AD (скрипт из этой статьи) и при изменении оповещать администратора безопасности всплывающим уведомлением и письмом.
Итак, у нас имеется код, который нужно сохранить в PS1 файл. Добавим бесконечный цикл, который раз в минуту выполняет проверку:
while($true) <
#Ваш PS код
Start-Sleep –Seconds 60
>
Создать службу из скрипта PowerShell при помощи NSSM можно прямо из PowerShell :):
$NSSMPath = (Get-Command «C:\tools\nssm\win64\nssm.exe»).Source
Запустим новую службу:
Итак, вы создали и запустили новую службу Windows. Проверим, что она появилась в консоли управления службами services.msc
Служба CheckADGroupSrv действительно появилась, она настроена на автоматический запус и в данный момент запущена (Running). Как вы видите, ваш PowerShell скрипт запущен внутри процесса nssm.exe.
Чтобы служба могла отображать уведомления в сеанс пользователя (взаимодействовать с рабочим столом) нужно на вкладке “Вход в систему” (Log on) включить опцию “Разрешить взаимодействие с рабочим столом” (Allow service to interact with desktop).
Однако в Windows 10 1803 службу Interactive Services Detection Service полностью убрали из системы, и вы более не можете переключиться в нулевую сессию (Session 0), так что вы просто не увидите окна, которые выводятся из-под аккаунта System.
Вы можете изменить описание службы командой:
Чтобы удалить созданную службу можете воспользоваться командой sc delete или
Продукты и технологии:
Windows Services, Windows PowerShell, C#
В статье рассматриваются:
В этой статье представлен конечный результат этих усилий: новый и простой способ создания Windows-служб. Их можно писать на скриптовом языке в Windows PowerShell. Больше никакой компиляции, просто быстрые циклы «правка-тест», которые можно выполнять в любой системе, а не только на компьютере разработчика.
Я предлагаю обобщенный шаблон скрипта службы, PSService.ps1, который позволяет создавать и проверять новые Windows-службы в считанные минуты, используя лишь текстовый редактор наподобие Notepad (блокнота). Этот метод может сэкономить уйму времени и усилий любому, кто хочет поэкспериментировать с Windows-службами или даже предоставлять настоящие Windows-службы, если производительность не является критическим фактором. PSService.ps1 включен в сопутствующий этой статье пакет исходного кода.
Что такое Windows-служба?
Windows-службы — это программы, выполняемые в фоне без взаимодействия с пользователем. Например, веб-сервер, который «молча» отвечает на HTTP-запросы для веб-страниц из сети, является службой, равно как и мониторинговое приложение, просто записывающее показатели производительности или фиксирующее аппаратные события от датчиков.
Службы можно запускать автоматически при загрузке системы. Или запускать по требованию, когда они запрашиваются приложениями, которые полагаются на них. Службы выполняются в собственном сеансе Windows, отличном от UI-сеанса. Они работают в ряде системных процессов с тщательно выбранными правами для ограничения рисков, связанных с безопасностью.
Windows Service Control Manager
Службы управляются Windows Service Control Manager (SCM). SCM отвечает за конфигурирование служб, их запуск и остановку и т. д.
Панель управления SCM доступна через Control Panel | System and Security | Administrative Tools | Services. Как показано на рис. 1, она отображает список всех сконфигурированных служб с их названиями, описаниями, состоянием, типом запуска и именем пользователя.
Рис. 1. Windows Service Control Manager GUI в Windows 10
Для SCM также имеются интерфейсы командной строки.
Эти утилиты командной строки, хоть и присутствуют в Windows 10, теперь считаются устаревшими, и рекомендуется использовать функции управления службами Windows PowerShell, как будет описано далее.
Подвох Как net.exe, так и sc.exe используют «короткие» имена служб в одно слово, которые, к сожалению, не совпадают с более описательными названиями, отображаемыми в панели управления SCM. Чтобы получить соответствие между двумя именами, используйте команду get-service из Windows PowerShell.
Состояния службы
Службы могут находиться в разнообразных состояниях. Некоторые состояния обязательны, другие не обязательны. Два базовых состояния, которые должны поддерживаться всеми службами: остановлена (stopped) и запущена (started). Эти состояния соответственно отображаются как пустая ячейка или Running (Выполняется) в столбце Status на рис. 1.
Третье, не обязательное состояние — Paused (Приостановлена). И еще одно неявное состояние, поддерживаемое каждой службой, даже если оно нигде не упоминается, — Uninstalled (Удалена).
Служба может переходить между этими состояниями, как показано на рис. 2.
Рис. 2. Состояния службы
Наконец, существует несколько переходных состояний, которые службы могут поддерживать (не обязательно): StartPending, StopPending, PausePending, ContinuePending. Они полезны, только если переходы между состояниями занимают значительное время.
Функции управления службами в Windows PowerShell
Windows PowerShell является рекомендуемой оболочкой системного управления со времен Windows Vista. Она включает мощный скриптовый язык и обширную библиотеку функций для управления всеми аспектами ОС. Вот лишь некоторые из сильных сторон Windows PowerShell:
Windows PowerShell предоставляет много функций управления службами, известных как командлеты (cmdlets). Некоторые примеры показаны в табл. 1.
Табл. 1. Функции управления службами в Windows PowerShell
Имя функции | Описание |
Start-Service | Запускает одну или более остановленных служб |
Stop-Service | Останавливает одну или более выполняемых служб |
New-Service | Устанавливает новую службу |
Get-Service | Получает службы на локальном или удаленном компьютере вместе с их свойствами |
Set-Service | Запускает, останавливает и приостанавливает службу, а также изменяет ее свойства |
Чтобы получить полный список всех команд со строкой «service» в их именах, введите:
Чтобы получить список только функций управления службами, введите:
Как это ни удивительно, но в Windows PowerShell нет функции для удаления службы. Это один из редких случаев, когда по-прежнему приходится использовать старую утилиту sc.exe:
.NET-класс ServiceBase
Табл. 2. Некоторые свойства и методы класса ServiceBase
Член | Описание |
ServiceName | Краткое имя, используемое для идентификации службы в системе |
CanStop | Сообщает, можно ли остановить службу после того, как она запущена |
OnStart() | Действия, предпринимаемые при запуске службы |
OnStop() | Действия, предпринимаемые при остановке службы |
Run() | Регистрирует исполняемый файл службы в SCM |
Реализуя эти методы, служба будет управляемой SCM и сможет запускаться автоматически при загрузке системы или по требованию; кроме того, такую службу можно будет запускать или останавливать вручную через панель управления SCM, старыми командами net.exe/sc.exe или новыми функциями Windows PowerShell для управления службами.
Создание исполняемого файла из исходного кода на C#, встроенного в скрипт Windows PowerShell
создаст приложение hello.exe, которое выводит в консоль «Hello world!»:
Собираем все воедино
Возможности PSService.ps1 На основе всего того, что мы обсудили на данный момент, я могу создать ту службу Windows PowerShell, о которой я мечтал, — скрипт PSService.ps1, который:
Заметьте, что в этой статье я затронул лишь критически важные части проекта и реализации PSService.ps1. Скрипт-пример также содержит отладочный код и в какой-то мере поддерживает необязательную функциональность служб, но их описание здесь усложнило бы пояснения безо всякой необходимости.
Архитектура PSService.ps1 Скрипт организуется в серию разделов:
Глобальные переменные
Непосредственно за блоком Param скрипт PSService.ps1 содержит глобальные переменные, определяющие глобальные настройки, которые при необходимости можно изменять. Их значения по умолчанию приведены в табл. 3.
Табл. 3. Значения по умолчанию глобальных переменных
Переменная | Описание | Значение по умолчанию |
$serviceName | Однословное имя, используемое командами net start и другими | Базовое имя скрипта |
$serviceDisplayName | Более описательное название службы | Sample PowerShell Service |
$installDir | Куда устанавливаются файлы службы | $ |
$logFile | Имя файла, в который записываются сообщения службы | $ |
$logName | Имя журнала событий, в который записываются события службы | Application |
Используя базовое имя файла как имя службы (например, PSService для PSService.ps1), вы можете создавать несколько служб из одного и того же скрипта простым копированием этого скрипта, переименованием копии и последующей установкой копии.
Аргументы командной строки
Чтобы упростить использование, скрипт поддерживает аргументы командной строки, которые соответствуют переходам во все состояния, как показано в табл. 4.
Табл. 4. Аргументы командной строки для переходов состояний
Ключ | Описание |
-Start | Запуск службы |
-Stop | Остановка службы |
-Setup | Установка себя как службы |
-Remove | Удаление службы |
(Поддержка состояния paused [приостановлена] не реализована, но ее легко добавить, используя соответствующий ключ для перехода в это состояние.)
В табл. 5 показано еще несколько аргументов для управления, поддерживаемых скриптом.
Табл. 5. Поддерживаемые аргументы для управления
Каждый ключ перехода состояния имеет два режима работы.
Эти два случая можно различить в период выполнения, проверив имя пользователя: в первом случае это обычный пользователь (системный администратор), а во втором — реальный системный пользователь Windows. Системного пользователя можно идентифицировать примерно так:
Установка
Цель установки службы — сохранить копию ее файлов в локальном каталоге и объявить SCM об этом, чтобы тот знал, какую программу следует выполнить для запуска службы.
Вот последовательность операций, выполняемых при обработке ключа –Setup.
Заметьте, что, начав с единственного исходного скрипта Windows PowerShell (PSService.ps1), я получил в итоге три файла, установленных в C:\Windows\System32: PSService.ps1, PSService.pdb и PSService.exe. Эти три файла понадобится удалить при удалении службы. Для реализации установки включите две части кода в скрипт.
Рис. 3. Обработчик кода установки
Запуск
За управление службами отвечает SCM. Каждая операция запуска должна проходить через SCM, чтобы он мог отслеживать состояния служб. Поэтому, даже если пользователь хочет вручную инициировать запуск через скрипт службы, этот запуск должен быть выполнен как запрос к SCM. В этом случае последовательность операция перечислена ниже.
В итоге будут выполняться две задачи: PSService.exe и экземпляр PowerShell.exe, выполняющий PSService.ps1 –Service.
За управление службами отвечает SCM.
Все это реализуется тремя частями кода в скрипте.
Рис. 4. Обработчик стартового кода
Получение состояния службы
Обработчик –Status просто запрашивает у SCM состояние службы и передает его в конвейер вывода:
Но на этапе отладки вы можете столкнуться со сбоями скрипта, например из-за синтаксических ошибок в скрипте и т. п. В таких случаях состояние SCM может оказаться в конечном счете некорректным. Я попадал в такую ситуацию несколько раз, когда готовил эту статью. Чтобы помочь в диагностике такого рода проблем, целесообразно все перепроверять и провести поиск экземпляров –Service:
Остановка и удаление
Операции Stop и Remove, по сути, отменяют то, что было сделано операциями Start и Setup соответственно:
Кроме того, их реализация очень похожа на таковую для Setup и Start.
Запись событий в журнал
Службы выполняются в фоновом режиме без UI. Это затрудняет их отладку: как диагностировать, что именно сбоит, когда по своей природе они ничего не отображают? Обычный метод — вести запись всех сообщений об ошибках с временными метками, а также протоколировать важные события, прошедшие успешно, например переходы состояний.
Службы выполняются в фоновом режиме без UI. Это затрудняет их отладку: как диагностировать, что именно сбоит, когда по своей природе они ничего не отображают?
Скрипт-пример PSService.ps1 реализует два разных метода протоколирования и использует их обоих в стратегически важных точках (включая ранее показанные фрагменты кода, где эти методы были убраны, чтобы сделать понятнее базовые операции).
Рис. 5. Просмотр событий PSService
Рис. 6. Пример файла журнала
Функция Log упрощает запись таких сообщений, автоматически предваряя их временными метками по стандарту ISO 8601 и именем текущего пользователя:
Пример тестового сеанса
Вот как были сгенерированы предыдущие журналы:
Это показывает, как в принципе использовать службу. Учтите, что эти команды должны выполняться пользователем с правами локального администратора в сеансе Windows PowerShell, работающем под учетной записью Administrator. Заметьте, что скрипт PSService.ps1 сначала отсутствовал в пути, но появился после выполнения операции –Setup. (Первый вызов –Status без пути заканчивается неудачей;, а второй вызов –Status завершается успешно.)
Скрипт службы, написанный в Windows PowerShell, очень удобен для проверки концепции.
Адаптация службы
Чтобы создать собственную службу, просто сделайте следующее.
В остальной части скрипта ничего изменять не следует, кроме добавления поддержки новых средств SCM вроде состояния Paused.
Ограничения и проблемы
Скрипт службы должен запускаться в оболочке, выполняемой с правами администратора, а иначе вы будете получать разнообразные ошибки из-за отказа в доступе.
Пример скрипта работает в Windows версий от XP до 10 и в соответствующих серверных версиях. В Windows XP вы должны установить Windows PowerShell v2, который по умолчанию отсутствует. Скачайте и установите Windows Management Framework v2 for XP (bit.ly/1MpOdpV), включающую Windows PowerShell v2. Заметьте, что я очень мало тестировал в этой ОС, поскольку она больше не поддерживается.
Во многих системах выполнение скриптов Windows PowerShell запрещено по умолчанию. Если вы получаете ошибку наподобие «выполнение скриптов отключено в этой системе» при попытке запустить PSService.ps1, то используйте:
Более подробные сведения см. во врезке «Ссылки».
Очевидно, такой скрипт службы, как этот, не может сравниться по производительности с компилированной программой. Скрипт службы, написанный в Windows PowerShell, очень удобен для проверки концепции и для задач с низкими издержками в отношении производительности вроде мониторинга системы, кластеризации служб и т. д. Но для любой высокопроизводительной задачи рекомендуется переписать службу на C++ или C#.
Кроме того, объем занимаемой памяти превышает таковой у скомпилированной программы, так как требует загрузки полнофункционального интерпретатора Windows PowerShell в сеансе System. Но в современных компьютерах со многими гигабайтами памяти это не имеет особого значения.
Этот скрипт не имеет абсолютно никакого отношения к PsService.exe от Марка Руссиновича (Mark Russinovich). Я выбрал имя PSService.ps1 до того, как узнал о совпадении имен. В конечном счете я сохранил имя скрипта-примера таким, поскольку оно делает понятным предназначение скрипта. Конечно, если вы планируете поэкспериментировать со своей службой на основе Windows PowerShell, то должны переименовать его, чтобы получить уникальное имя службы из уникального базового имени скрипта!
Ссылки
Жан-Франсуа Лавуа (Jean-François Larvoire) работает на Hewlett-Packard Enterprise в Гренобле (Франция). В течение более 30 лет занимается разработкой программного обеспечения для BIOS персональных компьютеров, драйверов для Windows и для системного управления Windows и Linux. С ним можно связаться по адресу jf.larvoire@hpe.com.
Выражаю благодарность за рецензирование статьи эксперту JDH IT Solutions Джеффри Хиксу (Jeffery Hicks).