Как проверить, запущен ли сервис через командный файл, и запустить его, если он не запущен?
Я хочу написать командный файл, который выполняет следующие операции:
- Проверьте, запущен ли сервис
- Если он запущен, выйдите из пакета
- Если он не запущен, запустите службу
Образцы кода, которые я до сих пор гуглил, оказались неработоспособными, поэтому я решил не публиковать их.
Запуск услуги осуществляется:
net start "SERVICENAME"
- Как я могу проверить, работает ли служба, и как сделать оператор if в пакетном файле?
- Я немного смущен. Какой аргумент я должен передать на чистый старт? Название сервиса или его отображаемое имя?
13 ответов
Чтобы проверить состояние услуги, используйте 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"
)
)
Объяснение того, что он делает:
- Запрашивает свойства сервиса.
- Ищет строку, содержащую текст "STATE"
- Токенизирует эту строку и извлекает 3-й токен, который содержит состояние сервиса.
- Проверяет полученное состояние по строке "RUNNING"
Что касается вашего второго вопроса, аргумент, который вы хотите передать net start
это имя службы, а не отображаемое имя.
Для переключения службы используйте следующее;
NET START "Координатор распределенных транзакций" ||NET STOP "Координатор распределенных транзакций"
Вы можете использовать следующую команду, чтобы увидеть, работает служба или нет:
sc query [ServiceName] | findstr /i "STATE"
Когда я запускаю его для своего NOD32 Antivirus, я получаю:
STATE : 4 RUNNING
Если бы это было остановлено, я получил бы:
STATE : 1 STOPPED
Вы можете использовать это в переменной, чтобы затем определить, используете ли вы NET START или нет.
Имя службы должно быть именем службы, а не отображаемым именем.
Это должно сделать это:
FOR %%a IN (%Svcs%) DO (SC query %%a | FIND /i "RUNNING"
IF ERRORLEVEL 1 SC start %%a)
Независимая от языка версия.
@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
)
Для Windows Server 2012 ниже это то, что у меня работает. Замените только "SERVICENAME" на фактическое имя сервиса:
@ECHO OFF
SET SvcName = SERVICENAME
SC QUERYEX "% SvcName%" | НАЙТИ "ГОСУДАРСТВО" | НАЙТИ /v "RUNNING" > NUL && ( ECHO %SvcName% не работает ECHO START% SvcName%
NET START "%SvcName%" > NUL || (
ECHO "%SvcName%" wont start
EXIT /B 1
)
ECHO "%SvcName%" is started
EXIT /B 0
) || (ECHO "% SvcName%" работает EXIT /B 0)
Я только нашел эту ветку и хотел бы добавить к обсуждению, если человек не хочет использовать командный файл для перезапуска служб. В Windows есть опция, если вы идете в Сервисы, свойства сервиса, затем восстановление. Здесь вы можете установить параметры для услуги. Как перезапустить службу, если служба останавливается. Кроме того, вы можете даже сделать вторую неудачную попытку сделать что-то другое, как при перезагрузке компьютера.
Вы можете использовать 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 no nombre del servicio que se sesea processar. Puedes ver el nombre del servicio viendo las propiedades del servicio. (Замените MYSERVICE на имя службы, которая будет обработана. Вы можете увидеть название службы в свойствах службы.)
@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"
Связанный с ответом @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-разрядная версия) английский
Я также хотел, чтобы электронное письмо было отправлено, если служба была запущена таким образом, поэтому немного добавил в код @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.
)
)
)
)
Запуск Сервиса с использованием скрипта 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
}
}
Может быть, гораздо проще? Просто добавив в список ответов здесь:
@for /f "tokens=1,* delims=: " %%a in ('sc queryex state=Inactive') do net start "%%b"
@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