Как управлять службами в Powershell командлетами Service


30 сентября 2019


Получение списка и запуск служб Powershell Service и управление

Для управления службами в Powershell есть восемь команд с помощью которых мы можем контролировать весь процесс работы сервисов и создавать новые. Что бы увидеть весь список команд созданных в PS для работы с сервисами нужно выполнить:

Get-Command -Noun Service

Мы увидим следующие командлеты:

  • Get-Service - получение списка служб в Powershell.
  • New-Service - создание нового сервиса.
  • Restart-Service - перезапуск службы.
  • Resume-Service - восстанавливает работу остановленного сервиса.
  • Set-Service - изменение настроек.
  • Start-Service - запуск службы в Powershell.
  • Stop-Service - остановка.
  • Suspend-Service - приостановка работы (пауза).

Учитывайте, что в виде команд делается не полное управление сервисами. Например удаление делается через WMI, которое тоже будут рассмотрены.

Получение списка служб

Узнать статус всех служб можно так:

Get-Service

Получение списка служб в Powershell Get-Service

Каждый результат выдаваемый командами в PS представляет собою объект. Этот объект содержит разные свойства и методы. Свойства - это например имя или статус. По умолчанию мы видим не все свойства. Что бы узнать какие еще свойства есть у команды нужно выполнить следующее:

Get-Service | Get-Member -MemberType Properties

Свойства сервисов в Powershell

Часть свойств реализована в виде ключей. Попробуем вывести сразу все свойства всех сервисов, но в таком случая вывод будет сложно читаемый:

Get-Service | SELECT *

Возможно вывести только имена, статус и тип запуска:

Get-Service | Ft Name, Status, StartType

Тип запуска и статус служб Powershell

Или выведем информацию по одному сервису:

Get-Service "WinRM" | Ft Name, Status, StartType

У сервисов есть короткое имя и отображаемое. Так мы выведем оба:

Имена служб Powershell

В именах мы можем использовать маски, а это значит что мы можем не знать полное название и использовать знак * в том месте, где не уверены в названии или написании:

Get-Service -DisplayName "Win*" | Ft Name, DisplayName, Status, StartType

Powershell использование маски у сервисов

Не желательно указывать отображаемое имя так как язык операционных систем может быть разным и если вы выполняете командлеты удаленно, вероятно будут ошибки:

  • Cannot find any service with service name
  • Cannot find any service with display name
  • Не удается найти службу с отображаемым именем

Кроме этого есть два ключа, которые тоже поддерживают маски:

  • Include - включают поиск по какой-то маске или точному соответствию.
  • Exclude - исключает упоминание.

Можно сравнить разницу с прошлым примером:

Get-Service -Name "Win*" -Include "*RM" -Exclude "*mgmt","*Http*","*Defend" | Ft Name, Status, StartType

Powershell Get-Service Include ExcludeУ сервисов несколько статусов:

  • Running - запущен.
  • Stopped - остановлен.
  • Paused - приостановлен (пауза).

По каждому из них мы можем отфильтровать результат:

Get-Service | where -Property Status -eq Stopped

Powershell Service фильтрация по статусу

Кроме этого есть 3 типа запуска:

  • Automatic - автоматический запуск вместе с системой.
  • AutomaticDelayedStart - запуск после загрузки системы.
  • Manual - ручной запуск.
  • Disabled - отключенный.

Допустим, что у нас есть какая-то проблема в операционной системе и мы хотим проверить все сервисы, который автоматически запускаются при включении ОС. Для этого нам нужно использовать несколько условий, где статус не равен Running и тип запуска равен Automatic:

Get-Service | where -FilterScript {$_.Status -ne 'Running' -and $_.StartType -eq 'Automatic'} | ft 'Name','StartType','Status'

Powershell остановленные службы

Службы могут быть зависимы от других и для проверки этих свойств есть два параметра:

  • DependentServices - кто зависит от этого сервиса.
  • RequiredServices - от кого зависит этот сервис.
Get-Service -DisplayName 'Windows Remote Management (WS-Management)' -RequiredServices -DependentServices

WINRm зависимые службы Powershell

Аналогично параметрам команды выше есть свойства DependentServices и ServicesDependedOn (RequiredServices). Они выводят одно и то же.

Есть несколько свойств, которые не выведены в параметры - это:

  • CanPauseAndContinue - можно ли приостановить работу сервиса и возобновить.
  • CanShutdown - может ли быть выключен.
  • CanStop - может ли быть полностью остановлен.

Эти свойства так же можно увидеть в GUI. В командлете ниже я использую алиас gsv (короткое имя Get-Service):

gsv -ServiceName 'Winrm' | SELECT CanPauseAndContinue,CanShutdown,CanStop | fl

Powershell CanPauseAndContinue службы Powershell

Каждая команда PS, где присутствует параметр ComuterName, может быть выполнена удаленно. Для удаленного управления в Powershell нужны дополнительные настройки, которые уже описывались в предыдущей статье. 

Имена всех компьютеров, с которых мы хотим получить имена сервисов, можно указать через запятую:

gsv -ComputerName 'AD1','localhost' | where Status -eq 'Stopped' | Select MachineName,Name,Status,StartType

Powershell получение сервисов с удаленного компьютера 

 

Остановка, перезапуск и запуск служб

Чтобы в Powershell запустить службу и остановить достаточно указать только имя. Причем можно указывать как короткое и отображаемое имя:

Stop-Service -Name 'WinRM'
Start-Service -DisplayName 'Служба удаленного управления Windows (WS-Management)'

Можно выполнить получение, остановку и запуск в одну команду:

gsv 'WinR*' | Stop-Service | Start-Service

 Во большинстве командлетах PS, которые делают изменения, можно увидеть два параметра. Первый - это WhatIf, который покажет результат выполнения командлета, но не попытается ее выполнить. Такие параметры удобно использовать при выполнении сложных задач типа кластеров. Второй параметр Confirm, который потребует подтверждение перед выполнением. Вместе эти параметры не работают:

Stop-Service -DisplayName 'Windows Remote Management (WS-Management)' -Confirm

В запуске и остановке так же можно использовать параметры фильтрации, которые вы видели при получении статусов выше. Будьте осторожны перед выполнением так как вы можете остановить все службы:

Stop-Service 'WinR*' -Include '*M'
Start-Service 'WinR*' -Include '*M'

Powershell запуск служб

Если с сервисом работает другой сервис, то мы не завершим его работу и нужно указать дополнительный ключ Force:

Stop-Service 'WinRM' -Force

Если он не стоит появится ошибка:

  • Cannot stop service 'Remote Procedure Call (RPC) (RpcSs)' because it has dependent services. It can only be stopped if the Force flag is set.
  • Не удается получить доступ к зависимым службам "Удаленный вызов процедур (RPC) (RpcSs)".

Как уже было описано выше сервисы могут быть зависимы от других и в таком случае запуск может не получится. На примере ниже я получил все родительские сервисы (от которых зависит Spooler) и запустил их, а затем запустил требуемый:

$sub_services = Get-Service 'Spooler'
$sub_services.RequiredServices | Start-Service
$sub_services.Name | Start-Service

Перезапуск сервисов работает так же со всеми параметрами:

Restart-Service 'WinRM'

Удаленный запуск и остановка командлетами не предусмотрена, но это исправляется стандартными методами:

Invoke-Command -ComputerName 'AD1','localhost' -ScriptBlock {Start-Service 'WinRM'}

 

Восстановление и приостановка работ служб

Не каждую службу можно приостановить (Pause) и восстанавливть. Что бы увидеть все службы, у которых есть такая возможность, выполните:

Get-Service | where CanPauseAndContinue | select -Property Name,CanPauseAndContinue,DisplayName

Powershell восстановление работы служб 

Командой ниже мы получи, нажмем паузу и восстановим работу сервиса Winmgmt:

Get-Service -Name 'Winmgmt' | Suspend-Service | Resume-Service

Ошибки, если мы попытаемся остановить службу у которых нет такой возможности:

  • Service 'Windows Remote Management (WS-Management)' cannot be suspended because the service does not support beingsuspended or resumed. 
  • Не удается приостановить службу "Spooler", так как этой службой не поддерживается приостановка или возобновление.

В этих командах так же можно использовать параметры Include и Exclude, с масками. 

На скрипте ниже показана проверка возможности приостановки сервиса, если у него есть такая возможность. Если ее нет, то сервис остановит свою работу:

# Закомментировано от случайностей
#$srv = 'Winmgm*'
$srv_suspend_on = (Get-Service $srv).CanPauseAndContinue
if ($srv_suspend_on){Suspend-Service $srv}
else {Stop-Service $srv}

 

Изменение с Set-Service

Командлетом ниже я изменил тип запуска сервиса с отключенного на автоматический:

Set-Service 'WinRM' -StartupType Automatic

В случае изменения сервисов нельзя использовать маски *. 

В документации Microsoft говориться про возможность изменения на четыре режима со следующими названиями:

  1. Automatic
  2. AutomaticDelayedStart
  3. Disabled
  4. Manual

Во первых половина называется иначе и изменение не срабатывает. Возможно изменение не срабатывает из-за багов Windows Server 2019,может из-за зависимостей (в GUI все работает), но скорее всего дело в PS. При работе с WMI все срабатывает. Реальные варианты запуска такие:

  1. Automatic
  2. Boot
  3. Disabled
  4. Manual
  5. System

Через эту команду можно так же выполнить запуск и остановку:

Set-Service 'WinRM' -Status Stopped

Все возможные значения:

  • Paused
  • Running
  • Stopped

Можно изменить описание сервиса:

Set-Service 'WinRM' -Description 'что вы сделали с PS'

Powershell учетная запись сервиса и описание

Команды изменения можно выполнять удаленно:

Set-Service WinRM -ComputerName 'AD1' -StartupType Automatic

 

Создание сервисов с New-Service

Для создания сервиса необходимо указать два параметра - это имя и путь до бинарного файла:

New-Service -Name 'TestService' -BinaryPathName 'C:\test.exe'

В PS 5.1 не предусмотрена команда удаления, она появилась в версии 6.1, которая устанавливается отдельно и может работать иначе. Для удаления сервисов, а так же частичного изменения, используется WMI. Указывайте все возможные параметры, что бы в последующем не лезть в WMI.

Параметры, которые в последующем нельзя будет изменить через PS:

  • DisplayName - полное отображаемое имя.
  • Credential  - учетная запись, под которой будет происходить запуск.
  • DependsOn - от кого будет зависеть.
$credential = Get-Credential
New-Service -Name 'TestService1' -BinaryPathName 'C:\test.exe' -DisplayName 'Testing Services In Powershell' -Credential $credential -DependsOn WinRM

При объявлении переменной $credential у нас запросятся учетные данные (логин/пароль). По умолчанию сервис работает под текущим аккаунтом. Я создавал сервис на доменном компьютере и пока я не ввел FQDN вид user@domain.local я получал ошибку:

  • Service 'Testing Services In Powershell (TestService1)' cannot be created due to the following error: The account name is invalid or does not exist, or the password is invalid for the account name specified

Кроме этого есть параметры, которые возможно изменить через команды выше:

  • Description - описание.
  • StartupType - тип запуска.
New-Service 'InstallService' -BinaryPathName 'C:\test.exe' -Description 'Descr' -StartupType Automatic

 

Получение с помощью WMI класса

За работу со службами в WMI отвечает класс win32_service. Преимущества такого подхода в том, что тут можно посмотреть и изменить все детали работы сервисов. Более подробно WMI в Powershell мы уже рассматривали.

Что бы получить список аналогичный Get-Service выполните:

Get-WmiObject -Class 'Win32_Service' | ft

 Получение списка служб с помощью WMI в Powershell

В классе WMI можно увидеть больше свойств, которые можно использовать:

Get-WmiObject -Class 'Win32_Service' | Get-Member -MemberType Properties

Powershell свойства служб в WMI

Одно из преимуществ использования в WMI это то, что мы можем увидеть идентификатор процесса под которым работает сервис. Если сервис остановлен, то его идентификатор 0. Так мы увидим идентификатор процесса с именем WinRM и получим всю информацию по процессу:

$srv = Get-WmiObject -Class Win32_Service | Where -Property Name -eq 'WinRM'
$srv.ProcessId
Get-Process -Id $srv.ProcessId

Получение процесса сервиса в Powershell

О том как работать с процессами в Powershell мы писали в прошлой статье. 

С помощью WMI мы можем вернуть имя аккаунта, под которым запущена служба и ее описание. Используя параметр ComputerName это можно сделать удаленно на множестве компьютеров:

Get-WmiObject -ComputerName 'AD1','localhost' -Class Win32_Service | ft Name,StartName,Description -AutoSize

Имя аккаунта службы в Powershell

 

Изменение с помощью WMI класса

Для управления в WMI существую методы. Все методы класса можно получить так:

Get-WmiObject -Class 'Win32_Service' | Get-Member -MemberType Method

Powershell управление в WMI службами

Удалим сервис, который создавался через New-Service:

Get-WmiObject -Class 'Win32_Service' | Get-Member -MemberType Method

Удаление служб в Powershell

Для изменения паролей нужно использовать следующую конструкцию. После выполнения команды сервис нужно перезапустить:

# Логин пользователя
$user = 'ServiceUser'
# Пароль пользователя
$password = 'Pass0000'
# Имя сервиса
$srv_name = 'ServiceName'
$srv = Get-WmiObject -Class win32_service | where -Property Name -eq $srv_name
$srv.Change($null,$null,$null,$null,$null,$null,$null,$null,$null,$user,$password)

$null установлены у всех параметров, которые мы не хотим изменять. В нашем случае нужно изменить только логин и пароль и они указаны в переменных. Увидеть какие параметры не меняются с $null можно так:

$srv = get-wmiobject win32_service | where Name -eq Winrm
$srv.GetMethodParameters("change")
...

Теги: #powershell


Популярные тэги
О блоге
Этот блог представляет собой конспекты выученного материала, преобретенного опыта и лучшие практики в системном администрировании и программировании.