¿Cómo verificar si un servicio se está ejecutando a través de un archivo por lotes e iniciarlo, si no se está ejecutando?

Quiero escribir un archivo por lotes que realice las siguientes operaciones:

  • Verifica si un servicio se está ejecutando
    • Si se está ejecutando, salga del lote
    • Si no se está ejecutando, inicie el servicio

Las muestras de código que busqué en Google hasta ahora resultaron no funcionar, así que decidí no publicarlas.

El inicio de un servicio se realiza mediante:

net start "SERVICENAME" 
  1. ¿Cómo puedo verificar si un servicio se está ejecutando y cómo hacer una statement if en un archivo por lotes?
  2. Estoy un poco confundido. ¿Cuál es el argumento que tengo que pasar al inicio neto? El nombre del servicio o su nombre para mostrar?

Para verificar el estado de un servicio, use la sc query . Para los bloques en los archivos por lotes, verifique la documentación .

El siguiente código verificará el estado del servicio MyServiceName y lo iniciará si no se está ejecutando (el bloque if se ejecutará si el servicio no se está ejecutando):

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

Explicación de lo que hace:

  1. Consulta las propiedades del servicio.
  2. Busca la línea que contiene el texto “ESTADO”
  3. Tokeniza esa línea y saca el tercer token, que es el que contiene el estado del servicio.
  4. Comprueba el estado resultante contra la cadena “RUNNING”

En cuanto a su segunda pregunta, el argumento que querrá pasar al net start es el nombre del servicio, no el nombre para mostrar.

Para alternar un servicio, use lo siguiente;

NET START “Coordinador de transacciones distribuidas” || NET STOP “Coordinador de transacciones distribuidas”

Puede usar el siguiente comando para ver si un servicio se está ejecutando o no:

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

Cuando lo ejecuto para mi NOD32 Antivirus, obtengo:

 STATE : 4 RUNNING 

Si se detuvo, obtendría:

 STATE : 1 STOPPED 

Puede usar esto en una variable para luego determinar si usa NET START o no.

El nombre del servicio debe ser el nombre del servicio, no el nombre para mostrar.

Deberias hacer eso:

 FOR %%a IN (%Svcs%) DO (SC query %%a | FIND /i "RUNNING" IF ERRORLEVEL 1 SC start %%a) 

Versión independiente del lenguaje.

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

Acabo de encontrar este hilo y quería agregar a la discusión si la persona no quiere usar un archivo por lotes para reiniciar los servicios. En Windows hay una opción si va a Servicios, propiedades del servicio y luego a recuperación. Aquí puede establecer parámetros para el servicio. Me gusta reiniciar el servicio si el servicio se detiene. Además, incluso puede hacer que un segundo bash fallido haga algo diferente al reiniciar la computadora.

Cuando se usa Windows en Español, el código debe quedar asi (cuando se usa Windows en español, el código es):

 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. (Reemplace MYSERVICE con el nombre del servicio que se procesará. Puede ver el nombre del servicio en las propiedades del servicio).

 @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" 

También quería un correo electrónico enviado si el servicio se inició de esta manera, así que agregué un poco al código @Ic, pensé que lo publicaría en caso de que ayudara a alguien. Utilicé SendMail pero hay otras opciones de línea de comandos. ¿Cómo enviar un correo electrónico simple desde un archivo por lotes de 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. ) ) ) ) 

Iniciando el servicio usando la secuencia de comandos de Powershell. Puede vincular esto al planificador de tareas y activarlo en intervalos o según sea necesario. Cree esto como un archivo PS1, es decir, archivo con la extensión PS1 y luego permita que este archivo se desencadene desde el progtwigdor de tareas.

Para iniciar el servicio de parada

en el progtwigdor de tareas si lo está usando en el servidor, use esto en argumentos

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

verificar ejecutando el mismo en cmd si funciona debería funcionar en el progtwigdor de tareas también

 $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 } } 
 @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 

Relacionado con la respuesta de @DanielSerrano, me han mordido recientemente por la localización del comando sc.exe , concretamente en español. Mi propuesta es señalar la línea y el token que contiene el estado del servicio numérico e interpretarlo, que debería ser mucho más robusto:

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

Probado con:

  • Windows XP (32 bits) Inglés
  • Windows 10 (32 bits) español
  • Windows 10 (64 bit) Inglés