Come verificare se un servizio è in esecuzione tramite file batch e avviarlo, se non è in esecuzione?


90

Voglio scrivere un file batch che esegua le seguenti operazioni:

  • Controlla se un servizio è in esecuzione
    • Se è in esecuzione, esci dal batch
    • Se non è in esecuzione, avvia il servizio

Gli esempi di codice che ho cercato su Google finora si sono rivelati non funzionanti, quindi ho deciso di non pubblicarli.

L'avvio di un servizio viene eseguito da:

net start "SERVICENAME"
  1. Come posso verificare se un servizio è in esecuzione e come creare un'istruzione if in un file batch?
  2. Sono un po 'confuso. Qual è l'argomento che devo trasmettere al net start? Il nome del servizio o il nome visualizzato?

3
Programmazione sporca: quando l'unica cosa da fare è avviare il servizio se non è in esecuzione, è sufficiente emettere il comando di avvio. Se non è in esecuzione, avvierà il servizio. Se è in esecuzione, viene visualizzato un messaggio di errore ma il servizio è in esecuzione (e non si ferma). Sporco ma funziona. Tuttavia, quando vuoi eseguire altri commenti solo se devi avviare il servizio, allora vai definitivamente con la versione più pulita da lc.
Peter Schuetze

@Peter Schuetze: Sì, la tua obiezione è corretta se avviare il servizio è l'unico scopo. Ho anche incluso gli inizi di registrazione eccetera, quindi sono rimasto fedele alla soluzione di lc.
citronas

Risposte:


163

Per controllare lo stato di un servizio, usa sc query <SERVICE_NAME>. Se si blocca in file batch, controllare la documentazione .

Il codice seguente controllerà lo stato del servizio MyServiceNamee lo avvierà se non è in esecuzione (il blocco if verrà eseguito se il servizio non è in esecuzione):

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

Spiegazione di cosa fa:

  1. Interroga le proprietà del servizio.
  2. Cerca la riga contenente il testo "STATE"
  3. Tokenizza quella riga ed estrae il terzo token, che è quello contenente lo stato del servizio.
  4. Verifica lo stato risultante rispetto alla stringa "RUNNING"

Per quanto riguarda la tua seconda domanda, l'argomento a cui vuoi passare net startè il nome del servizio, non il nome visualizzato.


Eccezionale. Grazie per i tuoi sforzi. Purtroppo non funziona? Forse sono troppo stupido per questo. Ho sostituito "MyServiceName" con "SCardSvr" (con escape) come test, ho inserito tutto in un file batch, l'ho eseguito, ma il servizio non si avvia. Anche se sostituisco net start con qualcos'altro, come la stampa in un file, non verrà eseguito. Ti dispiacerebbe dare una seconda occhiata per favore? =)
citronas

Ops, avevo alcune cose extra nella prima riga lì ... Prova questo. E se non funziona, cosa succede quando esegui sc query "SCardSvr"da una riga di comando?
lc.

1
Hai "SCardSvr" tra virgolette? Non credo che dovrebbe essere,
LittleBobbyTables - Au Revoir

@ LittleBobbyTables: hai ragione. Senza virgolette ha funzionato. Sono così stupido Sorry Grazie per il vostro aiuto
citronas

@ Mark Buono da notare. Immagino che dovrai sostituire quella stringa con quello che deve essere per la lingua del sistema operativo di destinazione. Presumo anche "RUNNING".
lc.

34

Per attivare / disattivare un servizio, utilizzare quanto segue;

NET START "Distributed Transaction Coordinator" || NET STOP "Distributed Transaction Coordinator"


1
Funziona a causa del codice di uscita dall'inizio. Se il comando di avvio fallisce è probabilmente perché è già in esecuzione (e in entrambi i casi interromperlo successivamente non farà male), quindi prova a fermarlo.
lc.

3
il comando è strutturato in modo tale che se net start fallisce, lo interrompe (a causa di || che significa altro), ma se net start viene eseguito, net stop non viene eseguito. brillante!
Doctor DOS

1
Questa è la risposta migliore secondo me, e forse @citronas dovrebbe considerare di contrassegnarla come risposta accettata: semplice, intelligente ed elegante e si adatta a un sito come StackOverflow. Falla semplice!
Sopalajo de Arrierez

2
Non per essere pignoli (OK, forse solo un po '), ma la ||realtà è un ORoperatore, anche se in questo caso è funzionalmente una ELSEdichiarazione. Questa è una differenza sottile ma importante. Ho ancora il mio +1: lo faccio sempre nello script di shell Unix / Linux, non so perché non ho mai pensato di farlo in batch di Windows.
Doug R.

Questo sembra pericolosamente semplificato. Non vorrei mai usarlo per qualcosa che stavo automatizzando per l'elaborazione in batch o per dare a qualcun altro da usare ... ma è proprio quello che il medico ha ordinato per un'icona rapida che posso mettere sul mio desktop per un servizio di cui ho bisogno passare rapidamente di tanto in tanto.
Joel Coehoorn

19

È possibile utilizzare il seguente comando per vedere se un servizio è in esecuzione o meno:

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

Quando lo eseguo per il mio NOD32 Antivirus, ottengo:

STATE                       : 4 RUNNING

Se fosse stato interrotto, avrei ottenuto:

STATE                       : 1 STOPPED

È possibile utilizzarlo in una variabile per determinare se si utilizza NET START o meno.

Il nome del servizio dovrebbe essere il nome del servizio, non il nome visualizzato.


1
Grazie per il tuo aiuto, mentre provo a integrare ciò che hai pubblicato, ho aumentato molto le mie capacità di batch;)
citronas

14

Dovrebbe farlo:

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

10

Versione indipendente dalla lingua.

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

Sì! "Spazio" colpisce sempre all'improvviso alla schiena!
Dr.eel

2
Risposta quasi perfetta. Correggerei solo questa riga: Net start "% ServiceName%"> nul || (
Cesar

Ho reso lo script universale, quindi mi consente di utilizzarlo nelle attività di pianificazione di Windows. Basta sostituire Set ServiceName=Jenkinscon Set ServiceName=%~1e chiamarlo comewatch-service.bat "Jenkins"
Dr.eel

@ Ant_222 Utilizza "queryex" invece di "query", che dipende dalla lingua. E perché pensi che non sia batch di Windows? Hai provato ad usarlo?
Dr.eel

5

Ho appena trovato questo thread e volevo aggiungerlo alla discussione se la persona non desidera utilizzare un file batch per riavviare i servizi. In Windows c'è un'opzione se vai su Servizi, proprietà del servizio, quindi ripristino. Qui puoi impostare i parametri per il servizio. Come riavviare il servizio se il servizio si interrompe. Inoltre, puoi anche fare in modo che un secondo tentativo fallito faccia qualcosa di diverso come riavviare il computer.


2
Questa è una risposta utile, tuttavia è importante notare che funzionerà solo se il servizio si è fermato con exit (-1). Se il servizio è stato chiuso correttamente (anche con un messaggio di errore) il ripristino automatico non si attiverà. Inoltre, non si attiverà se il servizio è stato terminato manualmente dall'utente.
Art Gertner

@sagelightning: abbiamo bisogno dell'accesso come amministratore per provare in questo modo.
Kumar M

@ArtGertner - Uccidere (tramite task manager) un processo di servizio verrà interpretato come "crash" e attiverà un ripristino.
Martin Ba

3

Se usi Windows en Español, el código debe quedar asi (quando usi Windows in spagnolo, il codice è):

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. (Sostituisci MYSERVICE con il nome del servizio da elaborare. Puoi vedere il nome del servizio nelle proprietà del servizio.)


10
Sarà meglio per tutti se scrivi la tua risposta in inglese.
j0k

2
Non sono sicuro del motivo per cui il voto negativo. Questo è un punto importante e un motivo per evitare, se possibile, confronti tra stringhe. In questo caso è necessario modificare la stringa in base alla lingua predefinita dell'installazione di Windows di destinazione.
lc.

2
@lc: sarebbe ragionevole includere una risposta per ogni lingua? Potrebbe essere più utile fare riferimento (o includere) una risorsa che dice quale stringa cercare per una data lingua.
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

Per Windows Server 2012 di seguito è riportato ciò che ha funzionato per me. Sostituisci solo "SERVICENAME" con il nome del servizio effettivo:

@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

Volevo anche inviare un'e-mail se il servizio è stato avviato in questo modo, quindi ho aggiunto un po 'al codice @Ic ho pensato di pubblicarlo nel caso in cui aiutasse qualcuno. Ho usato SendMail ma ci sono altre opzioni della riga di comando Come inviare una semplice e-mail da un file batch di 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

Avvio del servizio utilizzando lo script Powershell. È possibile collegarlo all'utilità di pianificazione e attivarlo a intervalli o secondo necessità. Crealo come file PS1, ovvero file con estensione PS1, quindi lascia che questo file venga attivato dall'utilità di pianificazione.

Per avviare il servizio di arresto

nell'utilità di pianificazione se lo stai usando sul server, usalo negli argomenti

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

verifica eseguendo lo stesso su cmd se funziona dovrebbe funzionare anche sull'utilità di pianificazione

$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

In relazione alla risposta di @DanielSerrano, recentemente sono stato morso dalla localizzazione del sc.execomando, cioè in spagnolo. La mia proposta è di individuare la linea e il segno che detiene lo stato del servizio numerico e interpretarlo, che dovrebbe essere molto più 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
  )
)

Testato con:

  • Windows XP (32 bit) inglese
  • Windows 10 (32 bit) spagnolo
  • Windows 10 (64 bit) inglese

0

Forse in un modo molto più semplice? Basta aggiungere all'elenco delle risposte qui:

@for /f "tokens=1,* delims=: " %%a in ('sc queryex state=Inactive') do net start "%%b"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.