Как проверить, запущена ли служба через командный файл, и запустить ее, если она не запущена?

91

Я хочу написать командный файл, который выполняет следующие операции:

  • Проверьте, запущена ли служба
    • Если он запущен, выйдите из партии
    • Если он не запущен, запустите службу

Примеры кода, которые я искал в Google, оказались неработоспособными, поэтому я решил не публиковать их.

Запуск службы осуществляется:

net start "SERVICENAME"
  1. Как я могу проверить, запущена ли служба, и как сделать оператор if в пакетном файле?
  2. Я немного запутался. Какой аргумент я должен передать чистому старту? Название сервиса или его отображаемое имя?
цитроны
источник
3
Грязное программирование: когда единственное, что вы хотите сделать, это запустить службу, если она не запущена, просто введите команду запуска. Если он не запущен, он запустит службу. Если он запущен, вы получите сообщение об ошибке, но служба работает (и не останавливается). Грязно, но работает. Однако, если вы хотите выполнить другие комментарии только в том случае, если вам нужно было запустить службу, обязательно используйте более чистую версию от lc.
Peter Schuetze
@Peter Schuetze: Да, ваше возражение правильное, если единственной целью является запуск службы. Я также включил ведение журнала и так далее, поэтому я придерживался решения lc.
citronas 09

Ответы:

164

Чтобы проверить состояние службы, используйте sc query <SERVICE_NAME>. Информацию о блоках if в пакетных файлах см. В документации .

Следующий код проверит состояние службы MyServiceNameи запустит ее, если она не запущена (блок if будет выполнен, если служба не запущена):

for /F "tokens=3 delims=: " %%H in ('sc query "MyServiceName" ^| findstr "        STATE"') do (
  if /I "%%H" NEQ "RUNNING" (
   REM Put your code you want to execute here
   REM For example, the following line
   net start "MyServiceName"
  )
)

Объяснение того, что он делает:

  1. Запрашивает свойства службы.
  2. Ищет строку, содержащую текст "СОСТОЯНИЕ"
  3. Токенизирует эту строку и извлекает третий токен, который содержит состояние службы.
  4. Проверяет результирующее состояние по строке "RUNNING"

Что касается вашего второго вопроса, аргумент, который вы захотите передать, net start- это имя службы, а не отображаемое имя.

lc.
источник
Потрясающие. Спасибо за ваши усилия. К сожалению, не работает? Может, я слишком глуп для этого. Я заменил «MyServiceName» на «SCardSvr» (экранированный) в качестве теста, поместил все в пакетный файл, выполнил его, но служба не запускается. Даже если я заменю net start чем-то другим, например печатью в файл, он не будет выполнен. Не могли бы вы взглянуть еще раз? =)
citronas
Ой, у меня там в первой строке было кое-что лишнее ... Попробуй. И если это не сработает, что произойдет, если вы запустите sc query "SCardSvr"из командной строки?
lc.
1
У вас в кавычках стоит "SCardSvr"? Я не верю, что так должно быть,
LittleBobbyTables - Au Revoir
@LittleBobbyTables: Вы правы. Без кавычек заставил работать. Я такой тупой: - | Спасибо за вашу помощь
citronas
@Mark Приятно отметить. Думаю, вам придется заменить эту строку на то, что нужно для языка целевой ОС. Я тоже предполагаю "БЕГ".
lc.
34

Для переключения службы используйте следующее:

NET START «Координатор распределенных транзакций» || NET STOP «Координатор распределенных транзакций»

Coops
источник
1
Работает из-за кода выхода с самого начала. Если команда запуска не работает, вероятно, потому, что она уже запущена (и в любом случае ее последующая остановка не повредит), поэтому вы пытаетесь ее остановить.
lc.
3
команда построена таким образом, что если net start завершается неудачно, она затем останавливает ее (из-за символа ||, что означает else), но если net start выполняется, то net stop не выполняется. молодец!
Doctor DOS
1
На мой взгляд, это лучший ответ, и, возможно, @citronas стоит подумать о том, чтобы пометить его как принятый: простой, умный и элегантный, который подходит для такого сайта, как StackOverflow. Сделай это проще!
Sopalajo de Arrierez
2
Не быть nitpicky (ОК, может быть , только немного), но ||на самом деле является ORоператором, хотя в данном случае это функциональноELSE заявление. Это тонкое, но важное отличие. У меня все еще есть +1 - я все время делаю это в сценариях оболочки Unix / Linux, не знаю, почему я никогда не думал делать это в пакетном режиме Windows.
Дуг Р.
Это кажется опасно упрощенным. Я никогда не хотел бы использовать его для чего-то, что я автоматизировал для пакетной обработки или отдавал кому-то другому ... но это именно то, что доктор заказал для быстрого значка, который я могу разместить на своем рабочем столе для службы, которая мне нужна время от времени быстро переключайтесь.
Джоэл Кохорн
20

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

sc query [ServiceName] | findstr /i "STATE"

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

STATE                       : 4 RUNNING

Если бы его остановили, я бы получил:

STATE                       : 1 STOPPED

Вы можете использовать это в переменной, чтобы затем определить, используете ли вы NET START или нет.

Имя службы должно быть именем службы, а не отображаемым именем.

LittleBobbyTables - Au Revoir
источник
1
Спасибо за вашу помощь, пока я пытаюсь интегрировать то, что вы опубликовали, я значительно увеличил свои навыки работы с
пакетами
14

Это должно сработать:

FOR %%a IN (%Svcs%) DO (SC query %%a | FIND /i "RUNNING"
IF ERRORLEVEL 1 SC start %%a)
Кристина Брукс
источник
12

Независимая от языка версия.

@Echo Off
Set ServiceName=Jenkins


SC queryex "%ServiceName%"|Find "STATE"|Find /v "RUNNING">Nul&&(
    echo %ServiceName% not running 
    echo Start %ServiceName%

    Net start "%ServiceName%">nul||(
        Echo "%ServiceName%" wont start 
        exit /b 1
    )
    echo "%ServiceName%" started
    exit /b 0
)||(
    echo "%ServiceName%" working
    exit /b 0
)
Доктор эл
источник
Ага! «Космос» всегда бьет внезапно в спину!
Dr.eel 08
2
Почти идеальный ответ. Я бы просто исправил эту строку: Net start "% ServiceName%"> nul || (
Cesar
Я сделал сценарий универсальным, поэтому он позволяет мне использовать его в задачах планировщика Windows. Просто замените Set ServiceName=Jenkinsна Set ServiceName=%~1и назовите это какwatch-service.bat "Jenkins"
Dr.eel
@ Ant_222 Он использует queryex вместо query, который зависит от языка. А почему вы думаете, что это не Windows batch? Вы пробовали его использовать?
Dr.eel
5

Я только что нашел эту ветку и хотел добавить в обсуждение, если человек не хочет использовать командный файл для перезапуска служб. В Windows есть опция, если вы перейдете в Сервисы, свойства службы, затем восстановление. Здесь вы можете установить параметры услуги. Хотелось бы перезапустить службу, если служба остановится. Кроме того, у вас даже может быть вторая неудачная попытка сделать что-то другое, например, перезагрузить компьютер.

молния
источник
2
Это полезный ответ, однако важно отметить, что он будет работать, только если служба остановлена ​​с помощью exit (-1). Если служба завершилась корректно (даже с сообщением об ошибке), автоматическое восстановление не сработает. Он также не сработает, если служба была убита пользователем вручную.
Art Gertner
@sagelightning: Нам нужен доступ администратора, чтобы попробовать этот способ.
Kumar M
@ArtGertner - завершение (через диспетчер задач) процесса обслуживания будет интерпретировано как «сбой» и вызовет восстановление.
Мартин Ба
3

Cuando se использует Windows en Español, el código debe quedar asi (при использовании Windows на испанском языке код следующий):

for /F "tokens=3 delims=: " %%H in ('sc query MYSERVICE ^| findstr "        ESTADO"') do (
  if /I "%%H" NEQ "RUNNING" (
    REM Put your code you want to execute here
    REM For example, the following line
    net start MYSERVICE
  )
)

Reemplazar MYSERVICE с номером обслуживания, который находится в процессе обработки. Puedes ver el nombre del servicio viendo las propiedades del servicio. (Замените MYSERVICE названием службы, которая будет обрабатываться. Вы можете увидеть имя службы в ее свойствах.)

Даниэль Серрано
источник
10
Всем будет лучше, если вы напишете свой ответ по-английски.
j0k 03
2
Не уверен, почему голос против. Это важный момент и причина по возможности избегать сравнения строк. В этом случае вам необходимо изменить строку в зависимости от языка по умолчанию целевой установки Windows.
lc.
2
@lc: Было бы разумно включать ответ для каждого языка? Было бы более полезно сослаться на (или включить) ресурс, в котором указано, в какой строке искать данный язык.
Mike Bailey
2
@echo off

color 1F


@sc query >%COMPUTERNAME%_START.TXT


find /I "AcPrfMgrSvc" %COMPUTERNAME%_START.TXT >nul

IF ERRORLEVEL 0 EXIT

IF ERRORLEVEL 1 NET START "AcPrfMgrSvc"
Логан78
источник
2

Для Windows Server 2012 у меня сработало то, что ниже. Замените только "SERVICENAME" фактическим названием службы:

@ECHO OFF
SET SvcName=SERVICENAME

SC QUERYEX "%SvcName%" | FIND "STATE" | FIND /v "RUNNING" > NUL && (
    ECHO %SvcName% is not running 
    ECHO START %SvcName%

    NET START "%SvcName%" > NUL || (
        ECHO "%SvcName%" wont start 
        EXIT /B 1
    )
    ECHO "%SvcName%" is started
    EXIT /B 0
) || (
    ECHO "%SvcName%" is running
    EXIT /B 0
)
Magige Daniel
источник
1

Я также хотел, чтобы электронное письмо было отправлено, если служба была запущена таким образом, поэтому добавил немного кода @Ic, просто подумал, что опубликую его, если это кому-то поможет. Я использовал SendMail, но есть и другие параметры командной строки. Как отправить простое электронное письмо из командного файла Windows?

set service=MyServiceName

for /F "tokens=3 delims=: " %%H in ('sc query %service% ^| findstr "        STATE"') do (
  if /I "%%H" NEQ "RUNNING" (

    net start %service%

    for /F "tokens=3 delims=: " %%H in ('sc query %service% ^| findstr "        STATE"') do (
      if /I "%%H" EQ "RUNNING" (
        SendMail /smtpserver localhost /to me@mydomain.com /from watchdog@mydomain.com /subject Service Autostart Notification /body Autostart on service %service% succeded.
      ) else (
        SendMail /smtpserver localhost /to me@mydomain.com /from watchdog@mydomain.com /subject Service Autostart Notification /body Autostart on service %service% failed.
      )
    )

  )
)
BYoung
источник
1

Запуск службы с использованием сценария Powershell. Вы можете связать это с планировщиком задач и запускать его через определенные промежутки времени или по мере необходимости. Создайте его как файл PS1, то есть файл с расширением PS1, а затем позвольте этому файлу запускаться из планировщика задач.

Для запуска остановки службы

в планировщике задач, если вы используете его на сервере, используйте это в аргументах

-noprofile -executionpolicy bypass -file "C: \ Service Restart Scripts \ StopService.PS1"

проверьте, запустив то же самое на cmd, если он работает, он также должен работать в планировщике задач

$Password = "Enter_Your_Password"
$UserAccount = "Enter_Your_AccountInfor"
$MachineName = "Enter_Your_Machine_Name"
$ServiceList = @("test.SocketService","test.WcfServices","testDesktopService","testService")
$PasswordSecure = $Password | ConvertTo-SecureString -AsPlainText -Force
$Credential = new-object -typename System.Management.Automation.PSCredential -argumentlist $UserAccount, $PasswordSecure 

$LogStartTime = Get-Date -Format "MM-dd-yyyy hh:mm:ss tt"
$FileDateTimeStamp = Get-Date -Format "MM-dd-yyyy_hh"
$LogFileName = "C:\Users\krakhil\Desktop\Powershell\Logs\StartService_$FileDateTimeStamp.txt" 


#code to start the service

"`n####################################################################" > $LogFileName
"####################################################################" >> $LogFileName
"######################  STARTING SERVICE  ##########################" >> $LogFileName

for($i=0;$i -le 3; $i++)
{
"`n`n" >> $LogFileName
$ServiceName = $ServiceList[$i]
"$LogStartTime => Service Name: $ServiceName" >> $LogFileName

Write-Output "`n####################################"
Write-Output "Starting Service - " $ServiceList[$i]

"$LogStartTime => Starting Service: $ServiceName" >> $LogFileName
Start-Service $ServiceList[$i]

$ServiceState = Get-Service | Where-Object {$_.Name -eq $ServiceList[$i]}

if($ServiceState.Status -eq "Running")
{
"$LogStartTime => Started Service Successfully: $ServiceName" >> $LogFileName
Write-Host "`n Service " $ServiceList[$i] " Started Successfully"
}
else
{
"$LogStartTime => Unable to Stop Service: $ServiceName" >> $LogFileName
Write-Output "`n Service didn't Start. Current State is - "
Write-Host $ServiceState.Status
}
}

#code to stop the service

"`n####################################################################" > $LogFileName
"####################################################################" >> $LogFileName
"######################  STOPPING SERVICE  ##########################" >> $LogFileName

for($i=0;$i -le 3; $i++)
{
"`n`n" >> $LogFileName
$ServiceName = $ServiceList[$i]
"$LogStartTime => Service Name: $ServiceName" >> $LogFileName

Write-Output "`n####################################"
Write-Output "Stopping Service - " $ServiceList[$i]

"$LogStartTime => Stopping Service: $ServiceName" >> $LogFileName
Stop-Service $ServiceList[$i]

$ServiceState = Get-Service | Where-Object {$_.Name -eq $ServiceList[$i]}

if($ServiceState.Status -eq "Stopped")
{
"$LogStartTime => Stopped Service Successfully: $ServiceName" >> $LogFileName
Write-Host "`n Service " $ServiceList[$i] " Stopped Successfully"
}
else
{
"$LogStartTime => Unable to Stop Service: $ServiceName" >> $LogFileName
Write-Output "`nService didn't Stop. Current State is - "
Write-Host $ServiceState.Status
}
}
К.Р. Ахил
источник
0
@Echo off

Set ServiceName=wampapache64

SC queryex "%ServiceName%"|Find "STATE"|Find /v "RUNNING">Nul&&(

echo %ServiceName% not running
echo  

Net start "%ServiceName%"


    SC queryex "%ServiceName%"|Find "STATE"|Find /v "RUNNING">Nul&&(
        Echo "%ServiceName%" wont start
    )
        echo "%ServiceName%" started

)||(
    echo "%ServiceName%" was working and stopping
    echo  

    Net stop "%ServiceName%"

)


pause
Айлиан Краспа
источник
0

Связанный с ответом @DanielSerrano, я недавно немного занимался локализацией sc.exeкоманды, а именно на испанском языке. Мое предложение состоит в том, чтобы точно указать линию и токен, которые содержат числовое состояние службы, и интерпретировать их, что должно быть намного более надежным:

@echo off

rem TODO: change to the desired service name
set TARGET_SERVICE=w32time

set SERVICE_STATE=
rem Surgically target third line, as some locales (such as Spanish) translated the utility's output
for /F "skip=3 tokens=3" %%i in ('""%windir%\system32\sc.exe" query "%TARGET_SERVICE%" 2>nul"') do (
  if not defined SERVICE_STATE set SERVICE_STATE=%%i
)
rem Process result
if not defined SERVICE_STATE (
  echo ERROR: could not obtain service state!
) else (
  rem NOTE: values correspond to "SERVICE_STATUS.dwCurrentState"
  rem https://msdn.microsoft.com/en-us/library/windows/desktop/ms685996(v=vs.85).aspx
  if not %SERVICE_STATE%==4 (
    echo WARNING: service is not running
    rem TODO: perform desired operation
    rem net start "%TARGET_SERVICE%"
  ) else (
    echo INFORMATION: service is running
  )
)

Протестировано с:

  • Windows XP (32-бит) английский
  • Windows 10 (32-бит) Испанский
  • Windows 10 (64-бит) английский
Helder Magalhães
источник
0

Может, способ намного проще? Просто добавляю сюда список ответов:

@for /f "tokens=1,* delims=: " %%a in ('sc queryex state=Inactive') do net start "%%b"
Герхард
источник