【问题标题】:How to check if a service is running via batch file and start it, if it is not running?如何通过批处理文件检查服务是否正在运行并启动它,如果它没有运行?
【发布时间】:2011-03-20 11:58:41
【问题描述】:

我想写一个执行以下操作的批处理文件:

  • 检查服务是否正在运行
    • 如果它正在运行,退出批处理
    • 如果没有运行,启动服务

到目前为止,我在 Google 上搜索的代码示例都无法正常工作,因此我决定不发布它们。

启动服务由:

net start "SERVICENAME"
  1. 如何检查服务是否正在运行,以及如何在批处理文件中创建 if 语句?
  2. 我有点困惑。我必须传递到网络开始的论点是什么?服务名称或其显示名称?

【问题讨论】:

  • 脏编程:如果你只想启动服务,如果它没有运行,只需发出启动命令。如果它没有运行,它将启动服务。如果它正在运行,那么您会收到一条错误消息,但服务正在运行(并且不会停止)。脏,但它的工作原理。但是,如果您只想在必须启动服务的情况下执行其他 cmets,则一定要使用来自 lc 的更清洁的版本。
  • @Peter Schuetze:是的,如果启动服务是唯一目的,您的反对意见是正确的。我还包括 logging start 等等,所以我坚持使用 lc 的解决方案。

标签: windows windows-services batch-file scheduled-tasks


【解决方案1】:

下面的 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
)

【讨论】:

    【解决方案2】:

    要检查服务的状态,请使用sc query <SERVICE_NAME>。对于批处理文件中的 if 块,check the documentation

    下面的代码会检查服务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. 标记该行,并提取第三个标记,它是包含服务状态的标记。
    4. 根据字符串“RUNNING”测试结果状态

    至于您的第二个问题,您要传递给net start 的参数是服务名称,不是显示名称。

    【讨论】:

    • 太棒了。谢谢你的努力。不幸的是它不起作用?也许我对这个太愚蠢了。我将“MyServiceName”替换为“SCardSvr”(转义)作为测试,将所有内容放入批处理文件中,执行它,但服务没有启动。即使我用其他东西替换 net start,比如打印到文件中,它也不会被执行。你介意再看一下吗? =)
    • 糟糕,我在第一行有一些额外的东西......试试这个。如果它不起作用,当你从命令行运行sc query "SCardSvr" 时会发生什么?
    • 引号中有“SCardSvr”吗?我不认为它应该是,
    • @LittleBobbyTables:你是对的。没有引号使它起作用。我太傻了:-|感谢您的帮助
    • 对任何路过的人的小评论。在 Powershell 下,您需要添加“.exe”:sc.exe query "MyServiceName"。由于scSet-Content 的别名(您可以使用Get-Alias "sc" 检查)。
    【解决方案3】:

    也许是更简单的方法?只需在此处添加答案列表即可:

    @for /f "tokens=1,* delims=: " %%a in ('sc queryex state=Inactive') do net start "%%b"
    

    【讨论】:

      【解决方案4】:

      与@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 位)英语

      【讨论】:

        【解决方案5】:

        使用 Powershell 脚本启动服务。您可以将其链接到任务计划程序并按间隔或根据需要触发它。 将此文件创建为 PS1 文件,即扩展名为 PS1 的文件,然后让此文件从任务调度程序中触发。

        启动停止服务

        如果你在服务器上使用它,在任务调度器中使用它在参数中

        -noprofile -executionpolicy bypass -file "C:\Service Restart Scripts\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
        }
        }
        

        【讨论】:

          【解决方案6】:

          语言独立版本。

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

          【讨论】:

          • 是的! “空间”总是突然击中你的后背!
          • 几乎完美的答案。我只是修复这一行: Net start "%ServiceName%">nul||(
          • 我已经使脚本通用,因此它允许我在 Windows 调度程序任务中使用。只需将Set ServiceName=Jenkins 替换为Set ServiceName=%~1 并像watch-service.bat "Jenkins" 一样调用它
          • @Ant_222 它使用 'queryex' 而不是 'query' 这取决于语言。为什么你认为它不是 Windows 批处理?你试过用吗?
          • 脚本中的 /v 是什么意思?也许你有所有这些脚本命令的链接?
          【解决方案7】:
          @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
          

          【讨论】:

            【解决方案8】:

            要切换服务,请使用以下命令;

            NET START“分布式事务 协调员”||NET STOP“分布式 事务协调员”

            【讨论】:

            • 它的工作原理是从开始的退出代码。如果启动命令失败,可能是因为它已经在运行(无论哪种方式随后停止它都不会受到伤害),所以你尝试停止它。
            • 该命令的结构是,如果 net start 失败,它会停止它(由于 || 表示 else),但如果 net start 运行,则 net stop 不会执行。太棒了!
            • 在我看来这是最好的答案,也许@citronas 应该考虑将其标记为可接受的答案:简单、智能、优雅,并且适合 StackOverflow 之类的网站。让它变得简单!
            • 不要吹毛求疵(好吧,也许只是一点点),但 || 实际上是一个 OR 运算符,尽管在这种情况下它在功能上是一个 @987654323 @ 陈述。这是一个微妙但重要的区别。仍然得到我的 +1 —— 我一直在 Unix/Linux shell 脚本中这样做,不知道为什么我从来没想过在 Windows 批处理中这样做。
            • 这似乎过于简单化了。我永远不想将它用于自动化批处理或提供给其他人使用的东西......但这正是医生订购的快速图标,我可以将它放在我自己的桌面上以获得我需要的服务不时快速切换。
            【解决方案9】:

            我刚刚找到了这个帖子,如果这个人不想使用批处理文件来重新启动服务,我想加入讨论。在 Windows 中,如果您转到“服务”、“服务属性”和“恢复”,则有一个选项。您可以在此处设置服务的参数。如果服务停止,喜欢重新启动服务。此外,您甚至可以让第二次失败尝试做一些不同的事情,例如重新启动计算机。

            【讨论】:

            • 这是一个有用的答案,但重要的是要注意,这仅在服务已通过 exit(-1) 停止时才有效。如果服务正常退出(即使有错误消息)自动恢复将不会触发。如果服务被用户手动终止,它也不会触发。
            • @sagelightning:我们需要管理员权限才能尝试这种方式。
            • @ArtGertner - 杀死(通过任务管理器)服务进程将被解释为“崩溃”并触发恢复。
            【解决方案10】:

            如果服务以这种方式启动,我还希望发送一封电子邮件,因此在@Ic 代码中添加了一些内容,只是想我会发布它以防它帮助任何人。我使用了 SendMail 但还有其他命令行选项How to send a simple email from a Windows batch file?

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

            【讨论】:

              【解决方案11】:
              @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"
              

              【讨论】:

                【解决方案12】:

                Cuando se use 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替换为要处理的服务名称,可以在服务属性上看到服务名称。)

                【讨论】:

                • 如果你用英文写你的答案对每个人都会更好。
                • 不知道为什么投反对票。这是一个重要的点,也是尽可能避免字符串比较的原因。在这种情况下,您必须根据目标 Windows 安装的默认语言更改字符串。
                • @lc:包含每种语言的答案是否合理?引用(或包含)说明要搜索给定语言的字符串的资源可能更有用。
                【解决方案13】:

                您可以使用以下命令查看服务是否正在运行:

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

                当我为我的 NOD32 Antivirus 运行它时,我得到:

                STATE                       : 4 RUNNING
                

                如果它被停止,我会得到:

                STATE                       : 1 STOPPED
                

                您可以在变量中使用它来确定您是否使用 NET START。

                服务名称应该是服务名称,而不是显示名称。

                【讨论】:

                • 感谢您的帮助,在尝试整合您发布的内容时,我大大提高了我的批处理技能;)
                【解决方案14】:

                应该这样做:

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

                【讨论】:

                  猜你喜欢
                  • 2023-03-08
                  • 1970-01-01
                  • 2021-06-26
                  • 1970-01-01
                  • 2018-05-11
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-08-19
                  相关资源
                  最近更新 更多