Як перевірити, чи запущена служба через пакетний файл, і запустити її, якщо вона не запущена?


90

Я хочу написати командний файл, який виконує такі операції:

  • Перевірте, чи працює служба
    • Якщо він запущений, закрийте пакет
    • Якщо він не запущений, запустіть службу

Зразки коду, які я досі загуглив, виявилися непрацюючими, тому я вирішив їх не розміщувати.

Запуск послуги виконується:

net start "SERVICENAME"
  1. Як я можу перевірити, чи запущена послуга, і як зробити оператор if у файлі команд?
  2. Я трохи розгублений. Який аргумент я маю передати для початку мережі? Назва послуги чи її відображувана назва?

3
Брудне програмування: коли єдине, що ви хочете зробити, це запустити службу, якщо вона не працює, просто виконайте команду start. Якщо він не запущений, він запустить службу. Якщо він запущений, ви отримуєте повідомлення про помилку, але служба працює (і не зупиняється). Брудно, але це працює. Однак, коли ви хочете виконати інші коментарі лише в тому випадку, якщо вам довелося запустити службу, тоді, безумовно, скористайтеся більш чистою версією від lc.
Peter Schuetze

@Peter Schuetze: Так, ваше заперечення є правильним, якщо запуск послуги є єдиною метою. Я також включив реєстрацію запусків тощо, тому я дотримувався розчину lc.
citronas

Відповіді:


163

Щоб перевірити стан послуги, скористайтеся sc query <SERVICE_NAME>. Якщо блоки в командних файлах, перевірте документацію .

Наступний код перевірить стан служби 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. Шукає рядок, що містить текст "STATE"
  3. Токенізує цей рядок і витягує 3-й маркер, який містить стан служби.
  4. Тестує результуючий стан щодо рядка "RUNNING"

Що стосується Вашого другого питання, аргументом, який Ви хочете передати, net startє ім'я послуги, а не відображуване ім'я.


Приголомшливо Дякую за ваші зусилля. На жаль це не працює? Можливо, я занадто дурний для цього. Я замінив "MyServiceName" на "SCardSvr" (екранований) як тест, помістив все в пакетний файл, виконав його, але служба не запускається. Навіть якщо я заміню net start на щось інше, наприклад друк у файл, він не буде виконаний. Не могли б ви поглянути ще раз, будь ласка? =)
citronas

На жаль, у мене там були додаткові речі в першому рядку ... Спробуйте це. А якщо це не спрацьовує, що відбувається, коли ви запускаєте sc query "SCardSvr"з командного рядка?
lc.

1
У вас є "SCardSvr" у лапках? Я не вірю, що так повинно бути,
LittleBobbyTables - Au Revoir

@LittleBobbyTables: Ви маєте рацію. Без лапок це змусило працювати. Я такий дурний: - | Дякуємо за допомогу
citronas

@Mark Приємно відзначити. Думаю, вам доведеться замінити цей рядок тим, що це потрібно для цільової мови ОС. Я припускаю, що це також "RUNNING".
lc.

34

Для перемикання послуги використовуйте наступне;

NET START "Координатор розподілених транзакцій" || NET STOP "Координатор розподілених транзакцій"


1
Це працює через код виходу з початку. Якщо команда start не вдається, це, мабуть, тому, що вона вже запущена (і в будь-якому випадку згодом її зупинка не зашкодить), тому спробуйте зупинити її.
lc.

3
команда побудована таким чином, що якщо мережевий запуск не вдається, він потім зупиняє його (через ||, що означає інше), але якщо запущений мережевий запуск, то сіт-стоп не виконується. блискуче!
Лікар DOS

1
На мою думку, це найкраща відповідь, і, можливо, @citronas варто подумати про те, щоб позначити її як прийняту відповідь: просту, розумну та елегантну і підходить для такого веб-сайту, як StackOverflow. Зробіть це просто!
Сопалахо де Аррієрес

2
Чи не бути nitpicky (ОК, може бути , тільки трохи), але ||насправді є ORоператором, хоча в даному випадку це функціональноELSE заяву. Це тонка, але важлива різниця. У мене все ще є +1 - я весь час роблю це в сценаріях оболонок Unix / Linux, не знаю, чому я ніколи не думав робити це в пакетній програмі Windows.
Даг Р.

Це здається небезпечно спрощеним. Я ніколи не хотів би використовувати його для чогось, що я автоматизував для пакетної обробки або передав комусь іншому ... але це саме те, що лікар замовив для швидкого значка, який я можу поставити на своєму робочому столі для послуги, яка мені потрібна швидко перемикайте час від часу.
Joel Coehoorn

19

Ви можете скористатися наступною командою, щоб побачити, запущена служба чи ні:

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

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

STATE                       : 4 RUNNING

Якби це було зупинено, я б отримав:

STATE                       : 1 STOPPED

Ви можете використовувати це у змінній, щоб потім визначити, чи використовуєте ви NET START чи ні.

Назва послуги повинна бути назвою послуги, а не відображуваною назвою.


1
Дякую за вашу допомогу, намагаючись інтегрувати те, що ви опублікували, я значно підвищую свої партійні навички;)
citronas


10

Мовна незалежна версія.

@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

2
Майже ідеальна відповідь. Я просто зафіксував би цей рядок: Чистий старт "% ServiceName%"> nul || (
Сезар,

Я зробив сценарій універсальним, тому він дозволяє мені використовувати його в завданнях Планувальника Windows. Просто замініть Set ServiceName=Jenkinsз Set ServiceName=%~1і назвати його якwatch-service.bat "Jenkins"
Dr.eel

@ Ant_222 Він використовує "queryex" замість "query", який залежить від мови. І чому ви думаєте, що це не пакет Windows? Ви пробували ним користуватися?
Dr.eel

5

Я просто знайшов цю тему і хотів додати до обговорення, якщо особа не хоче використовувати пакетний файл для перезапуску служб. У Windows є можливість, якщо ви перейдете до Служб, властивостей служби, а потім відновлення. Тут ви можете встановити параметри для послуги. Хочете перезапустити службу, якщо вона припиняється. Крім того, ви можете навіть повторно спробувати зробити щось інше, як при перезавантаженні комп’ютера.


2
Це корисна відповідь, однак важливо зазначити, що це спрацює лише в тому випадку, якщо служба зупинилася з виходом (-1). Якщо послуга вийшла з витонченим рухом (навіть із повідомленням про помилку), автоматичне відновлення не спрацює. Це також не спрацьовує, якщо послугу вбив користувач вручну.
Арт Гертнер

@sagelightning: Нам потрібен доступ адміністратора, щоб спробувати таким чином.
Кумар М

@ArtGertner - Вбивство (за допомогою диспетчера завдань) процес служби буде інтерпретовано як "збій" і спричинить відновлення.
Мартін Ба

3

Використовуйте 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 con el nombre del servicio que se desea procesar. Puedes ver el nombre del servicio viendo las propiedades del servicio. (Замініть MYSERVICE на ім'я послуги, що підлягає обробці. Ви можете побачити назву служби у властивостях служби.)


10
Для кожного буде краще, якщо ви напишете свою відповідь англійською мовою.
j0k

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"

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
)

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.
      )
    )

  )
)

1

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

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

у планувальнику завдань, якщо ви використовуєте його на сервері, використовуйте це в аргументах

-noprofile -executionpolicy bypass -file "C: \ Сценарії перезапуску служби \ 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-розрядна версія) англійська

0

Може, набагато простіший спосіб? Просто додавши до списку відповідей тут:

@for /f "tokens=1,* delims=: " %%a in ('sc queryex state=Inactive') do net start "%%b"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.