Stopping/Starting a remote Windows service and waiting for it to open/close

后端 未结 11 1506
广开言路
广开言路 2020-12-02 06:42

The top answer to this question tells me how to stop/start a remote service. Great. Now, all I need is to wait for the actual stop/start to complete. So, what I\'m looking f

相关标签:
11条回答
  • 2020-12-02 07:43

    What about powershell and WaitForStatus? Eg, the script below would restart SQL Server on a remote machine:

    $computer = "COMPUTER_NAME"
    $me = new-object -typename System.Management.Automation.PSCredential -argumentlist "DOMAIN\user", (convertto-securestring "password" -asplaintext -force)
    $restartSqlServer = { 
        $sqlServer = get-service mssqlserver
        $waitInterval = new-timespan -seconds 5
        if (-not ($sqlServer.Status -eq "Stopped")) {
            $sqlServer.Stop()
            $sqlServer.WaitForStatus('Stopped', $waitInterval) 
        }
        $sqlServer.Start()
        $sqlServer.WaitForStatus('Running', $waitInterval) 
    }     
    icm -ComputerName $computer -ScriptBlock $restartSqlServer -Credential $me 
    
    0 讨论(0)
  • 2020-12-02 07:43

    Edit on 10/20/2011 - updated my code. I posted it before fully debugging. Many thanks to Eric Falsken. What a great solution. I tweaked Eric's code (BTW look for a couple of typographical errors if you intend to use it). I added logging and some additional error-checking for some conditions Eric didn't account for. Since I'm most interested in a service restart (not just stopping and/or starting), I only built upon Eric's restart code. Anyway, I'm posting my version, hope you like it!

    @ECHO off
    :: This script originally authored by Eric Falsken http://stackoverflow.com/
    :: Revised for by George Perkins 10/20/2011
    IF [%1]==[] GOTO Usage
    IF [%2]==[] GOTO Usage
    
    :SetLocalVariables
    SET /A MyDelay=0 
    SET MyHours=%time:~0,2%
    IF %MyHours%==0 SET MyHours=00
    IF %MyHours%==1 SET MyHours=01
    IF %MyHours%==2 SET MyHours=02
    IF %MyHours%==3 SET MyHours=03
    IF %MyHours%==4 SET MyHours=04
    IF %MyHours%==5 SET MyHours=05
    IF %MyHours%==6 SET MyHours=06
    IF %MyHours%==7 SET MyHours=07
    IF %MyHours%==8 SET MyHours=08
    IF %MyHours%==9 SET MyHours=09
    SET MyMinutes=%time:~3,2%
    SET MySeconds=%time:~6,2%
    SET MyHundredths=%time:~9,2%
    SET MyMonth=%date:~4,2%
    SET MyDay=%date:~-7,2%
    SET MyCentury=%date:~-4,4%
    SET MyTimeStamp=%MyCentury%%MyMonth%%MyDay%%MyHours%%MyMinutes%%MySeconds%
    IF "%3" == "" (
             SET MyLog=C:\Temp
       ) ELSE (
             SET MyLog=%3
       ) 
    SET MyLogFile=%MyLog%\ServiceRestart%MyTimeStamp%.log
    ECHO.
    ECHO. >> %MyLogFile%
    ECHO ------------- ------------- %MyHours%:%MyMinutes%:%MySeconds%.%MyHundredths% %MyMonth%/%MyDay%/%MyCentury% ------------- ------------- 
    ECHO ------------- ------------- %MyHours%:%MyMinutes%:%MySeconds%.%MyHundredths% %MyMonth%/%MyDay%/%MyCentury% ------------- ------------- >> %MyLogFile% 
    ECHO Begin batch program %0. 
    ECHO Begin batch program %0. >> %MyLogFile%
    ECHO Logging to file %MyLogFile%. 
    ECHO Logging to file %MyLogFile%. >> %MyLogFile% 
    ECHO Attempting to restart service %2 on computer %1.
    ECHO Attempting to restart service %2 on computer %1. >> %MyLogFile%
    
    PING -n 1 %1 | FIND "TTL=" >> %MyLogFile%
    IF errorlevel 1 IF NOT errorlevel 2 GOTO SystemOffline
    SC \\%1 query %2 | FIND "FAILED 1060" >> %MyLogFile%
    IF errorlevel 0 IF NOT errorlevel 1 GOTO InvalidServiceName
    SC \\%1 query %2 | FIND "STATE" >> %MyLogFile%
    IF errorlevel 1 IF NOT errorlevel 2 GOTO SystemOffline
    
    :ResolveInitialState
    SET /A MyDelay+=1
    SC \\%1 query %2 | FIND "STATE" | FIND "RUNNING" >> %MyLogFile%
    IF errorlevel 0 IF NOT errorlevel 1 GOTO StopService
    SC \\%1 query %2 | FIND "STATE" | FIND "STOPPED" >> %MyLogFile%
    IF errorlevel 0 IF NOT errorlevel 1 GOTO StartService
    SC \\%1 query %2 | FIND "STATE" | FIND "PAUSED" >> %MyLogFile%
    IF errorlevel 0 IF NOT errorlevel 1 GOTO SystemOffline
    ECHO Service State is changing, waiting %MyDelay% seconds for service to resolve its state before making changes.
    ECHO Service State is changing, waiting %MyDelay% seconds for service to resolve its state before making changes. >> %MyLogFile%
    TIMEOUT /t %MyDelay% /nobreak >> %MyLogFile%
    GOTO ResolveInitialState
    
    :StopService
    SET /A MyDelay=0
    ECHO Stopping %2 on \\%1.
    ECHO Stopping %2 on \\%1. >> %MyLogFile%
    SC \\%1 stop %2 | FIND "FAILED" >> %MyLogFile%
    IF errorlevel 0 IF NOT errorlevel 1 GOTO Unstoppable
    
    :StoppingServiceDelay
    SET /A MyDelay+=1
    IF %MyDelay%==21 GOTO MaybeUnStoppable
    ECHO Waiting %MyDelay% seconds for %2 to stop.
    ECHO Waiting %MyDelay% seconds for %2 to stop. >> %MyLogFile%
    TIMEOUT /t %MyDelay% /nobreak >> %MyLogFile%
    :StoppingService
    SC \\%1 query %2 | FIND "STATE" | FIND "STOPPED" >> %MyLogFile%
    IF errorlevel 0 IF NOT errorlevel 1 GOTO StoppedService
    SC \\%1 query %2 | FIND "STATE" | FIND "STOP_PENDING" >> %MyLogFile%
    IF errorlevel 0 IF NOT errorlevel 1 GOTO StoppingServiceDelay
    GOTO StoppingServiceDelay
    
    :MaybeUnStoppable
    :: If we got here we waited approximately 3 mintues and the service has not stopped.
    SC \\%1 query %2 | FIND "NOT_STOPPABLE" >> %MyLogFile%
    IF errorlevel 0 IF NOT errorlevel 1 GOTO OneLastChance
    GOTO Unstoppable 
    
    :OneLastChance
    SC \\%1 stop %2 >> %MyLogFile%
    SET /A MyDelay+=1
    ECHO Waiting %MyDelay% seconds for %2 to stop.
    ECHO Waiting %MyDelay% seconds for %2 to stop. >> %MyLogFile%
    TIMEOUT /t %MyDelay% /nobreak >> %MyLogFile%
    SC \\%1 query %2 | FIND "STATE" | FIND "STOPPED" >> %MyLogFile%
    IF errorlevel 0 IF NOT errorlevel 1 GOTO StoppedService
    SC \\%1 query %2 | FIND "STATE" | FIND "RUNNING" >> %MyLogFile%
    IF errorlevel 1 IF NOT errorlevel 2 GOTO UnknownState
    SC \\%1 query %2 | FIND "NOT_STOPPABLE" >> %MyLogFile%
    IF errorlevel 0 IF NOT errorlevel 1 GOTO Unstoppable
    GOTO StoppingServiceDelay
    
    :StoppedService
    ECHO %2 on \\%1 is stopped.
    ECHO %2 on \\%1 is stopped. >> %MyLogFile%
    GOTO StartService
    
    :StartService
    SET /A MyDelay=0 
    ECHO Starting %2 on \\%1.
    ECHO Starting %2 on \\%1. >> %MyLogFile%
    SC \\%1 start %2 >> %MyLogFile%
    
    GOTO StartingService
    :StartingServiceDelay
    SET /A MyDelay+=1
    ECHO Waiting %MyDelay% seconds for %2 to start.
    ECHO Waiting %MyDelay% seconds for %2 to start. >> %MyLogFile%
    TIMEOUT /t %MyDelay% /nobreak >> %MyLogFile%
    :StartingService
    SC \\%1 query %2 | FIND "STATE" | FIND "RUNNING" >> %MyLogFile%
    IF errorlevel 1 IF NOT errorlevel 2 GOTO StartingServiceDelay
    
    :StartedService
    ECHO %2 on \\%1 is started.
    ECHO %2 on \\%1 is started. >> %MyLogFile%
    GOTO EndExit
    
    :SystemOffline
    ECHO Failure! Server \\%1 or service %2 is not accessible or is offline!
    ECHO Failure! Server \\%1 or service %2 is not accessible or is offline! >> %MyLogFile%
    ECHO See log file %MyLogFile% for details!
    GOTO EndExit
    
    :InvalidServiceName
    ECHO Failure! Service %2 is not valid!
    ECHO Failure! Service %2 is not valid! >> %MyLogFile%
    ECHO See log file %MyLogFile% for details!
    GOTO EndExit
    
    :UnknownState
    ECHO Failure! Service %2 in an unknown state and cannot be stopped!
    ECHO Failure! Service %2 in an unknown state and cannot be stopped! >> %MyLogFile%
    ECHO See log file %MyLogFile% for details!
    GOTO EndExit
    
    :UnStoppable
    ECHO Failure! Service %2 cannot be stopped! Check dependencies or system state.
    ECHO Failure! Service %2 cannot be stopped! Check dependencies or system state. >> %MyLogFile%
    ECHO See log file %MyLogFile% for details!
    GOTO EndExit
    
    :Usage
    ECHO Will restart a remote service, waiting for the service to stop/start (if necessary).
    ECHO.
    ECHO Usage:
    ECHO %0 [system name] [service name] [logfile path]
    ECHO Example: %0 server1 MyService C:\Temp\Log
    ECHO.
    GOTO EndExit
    
    :EndExit
    ECHO.
    ECHO %0 Ended.
    ECHO.
    
    0 讨论(0)
  • 2020-12-02 07:44

    I improved the script of Eric Falsken and revised by Gerorge Perkins.

    Changes:

    • now it is not only a restart script. The script can start, stop and restart a local or remote service;
    • removed logging (if you want this, you can use it simply by launching SCRIPT_NAME.bat > logfile.txt);
    • sparse optimizations.

      @ECHO off
      :: This script originally authored by Eric Falsken http://stackoverflow.com/
      :: Revised by George Perkins 10/20/2011
      :: Revised by Armando Contestabile 02/23/2015
      IF "%1"=="" GOTO Usage
      IF "%2"=="" GOTO Usage
      
      SET ACTION=%1
      SET SERVICENAME=%2
      
      IF "%3"=="" (
          SET SYSTEMNAME=%COMPUTERNAME%
      ) ELSE (
          SET SYSTEMNAME=%3
      )
      
      IF "%ACTION%" == "stop" (
          SET ACTION=STOP
      ) ELSE IF "%ACTION%" == "STOP" (
          SET ACTION=STOP
      ) ELSE IF "%ACTION%" == "start" (
          SET ACTION=START
      ) ELSE IF "%ACTION%" == "START" (
          SET ACTION=START
      ) ELSE IF "%ACTION%" == "restart" (
          SET ACTION=RESTART
      ) ELSE IF "%ACTION%" == "RESTART" (
          SET ACTION=RESTART
      ) ELSE GOTO Usage
      
      SET STATE=
      SET CURRENT_STATUS=
      SET /A DEFAULT_DELAY=5
      SET /A SLEEP_COUNT=0
      SET /A RESTARTED=0
      SET /A MAX_WAIT_PERIODS=5
      
      ECHO.
      ECHO Attempting to %ACTION% service %SERVICENAME% on computer %SYSTEMNAME%.
      
      PING -n 1 %SYSTEMNAME% | FIND "TTL=" >nul 2>&1
      IF ERRORLEVEL 1 IF NOT ERRORLEVEL 2 (
          ECHO Failure! Server \\%SYSTEMNAME% or service %SERVICENAME% is not accessible or is offline!
          EXIT /B 1
      )
      SC \\%SYSTEMNAME% query %SERVICENAME% | FIND "FAILED 1060" >nul 2>&1
      IF ERRORLEVEL 0 IF NOT ERRORLEVEL 1 (
          ECHO Failure! Service %SERVICENAME% is not valid!
          EXIT /B 2
      )
      SC \\%SYSTEMNAME% query %SERVICENAME% | FIND "STATE" >nul 2>&1
      IF ERRORLEVEL 1 IF NOT ERRORLEVEL 2 (
          ECHO Failure! Server \\%SYSTEMNAME% or service %SERVICENAME% is not accessible or is offline!
          EXIT /B 3
      )
      
      :Dispatch
      FOR /f "tokens=*" %%i IN ('SC \\%SYSTEMNAME% query %SERVICENAME% ^| FIND "STATE"') DO SET STATE=%%i
      
      ECHO %STATE% | FINDSTR /C:"1" >nul
      IF %ERRORLEVEL%==0 SET CURRENT_STATUS=STOPPED
      ECHO %STATE% | FINDSTR /C:"2" >nul
      IF %ERRORLEVEL%==0 SET CURRENT_STATUS=START_PENDING
      ECHO %STATE% | FINDSTR /C:"3" >nul
      IF %ERRORLEVEL%==0 SET CURRENT_STATUS=STOP_PENDING
      ECHO %STATE% | FINDSTR /C:"4" >nul
      IF %ERRORLEVEL%==0 SET CURRENT_STATUS=RUNNING
      ECHO %STATE% | FINDSTR /C:"5" >nul
      IF %ERRORLEVEL%==0 SET CURRENT_STATUS=CONTINUE_PENDING
      ECHO %STATE% | FINDSTR /C:"6" >nul
      IF %ERRORLEVEL%==0 SET CURRENT_STATUS=PAUSE_PENDING
      ECHO %STATE% | FINDSTR /C:"7" >nul
      IF %ERRORLEVEL%==0 SET CURRENT_STATUS=PAUSED
      
      ECHO Current status of service is %CURRENT_STATUS%
      
      IF NOT "%CURRENT_STATUS%"=="RUNNING" IF NOT "%CURRENT_STATUS%"=="STOPPED" IF NOT "%CURRENT_STATUS%"=="PAUSED" (
          IF "%SLEEP_COUNT%"=="%MAX_WAIT_PERIODS%" (
              ECHO Service state won't change. Script exececution is canceled.
              EXIT /B 4
          )
          ECHO Service State is changing, waiting %DEFAULT_DELAY% seconds...
          SLEEP %DEFAULT_DELAY%
          SET /A SLEEP_COUNT+=1
          GOTO Dispatch
      )
      
      IF "%ACTION%"=="START" (
          IF "%CURRENT_STATUS%"=="RUNNING" (
              ECHO Service %SERVICENAME% is running.
              GOTO EndExit
          ) ELSE (
              GOTO StartService
          )
      ) ELSE IF "%ACTION%"=="RESTART" (
          IF "%CURRENT_STATUS%"=="RUNNING" (
              IF %RESTARTED%==1 (
                  ECHO Service %SERVICENAME% restarted.
                  GOTO EndExit
              )
              SET /A SLEEP_COUNT=0
              GOTO StopService
          ) ELSE (
              SET /A RESTARTED=1
              GOTO StartService
          )
      ) ELSE IF "%ACTION%"=="STOP" (
          IF "%CURRENT_STATUS%"=="STOPPED"  (
              ECHO Service %SERVICENAME% is stopped.
              GOTO EndExit
          ) ELSE (
              GOTO StopService
          )
      )
      
      :StartService
      ECHO Starting %SERVICENAME% on \\%SYSTEMNAME%
      SC \\%SYSTEMNAME% start %SERVICENAME% >nul 2>&1
      SET SLEEP_COUNT=0
      GOTO Dispatch
      
      :StopService
      ECHO Stopping %SERVICENAME% on \\%SYSTEMNAME%
      SC \\%SYSTEMNAME% stop %SERVICENAME% >nul 2>&1
      SET SLEEP_COUNT=0
      GOTO Dispatch
      
      :Usage
      ECHO This script can start/stop/restart a local or remote service, waiting for the service to stop/start ^(if necessary^).
      ECHO.
      ECHO Usage:
      ECHO %0 ^<start^|stop^|restart^> ^<SERVICE^> [SYSTEM]
      ECHO.
      ECHO If no SYSTEM is provided, the script attempts to execute on the local system.
      EXIT /B 5
      
      :EndExit
      ECHO.
      EXIT /B 0
      
    0 讨论(0)
  • 2020-12-02 07:45

    Eric Falsken's solution works perfectly. +1.

    But I'd like to add that the timeout command would sometimes fail with error: "Input redirection is not supported, exiting the process immediately"

    To fix this I've had to replace the timeout command:

    timeout /t 2 /nobreak >NUL
    

    with the following:

    ping -n 2 127.0.0.1  1>NUL
    
    0 讨论(0)
  • 2020-12-02 07:45

    NET START and NET STOP shouldn't return until the service has indicated that the service has started or stopped successfully.

    0 讨论(0)
提交回复
热议问题