如何检查服务是否通过批处理文件运行并启动(如果未运行)?


90

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

  • 检查服务是否正在运行
    • 如果正在运行,请退出该批处理
    • 如果未运行,请启动服务

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

通过以下方式启动服务:

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

3
肮脏的编程:如果您唯一想做的就是在未运行的情况下启动服务,则只需发出启动命令即可。如果未运行,它将启动服务。如果它正在运行,则您会收到一条错误消息,但该服务正在运行(并且不会停止)。脏,但是可以用。但是,当您只想在必须启动服务时才执行其他注释时,请使用lc的更清洁版本。
Peter Schuetze 2012年

@Peter Schuetze:是的,如果启动服务是唯一目的,那么您的反对是正确的。我还记录了启动日志等内容,因此我坚持使用lc的解决方案。
香茅油2012年

Answers:


163

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

以下代码将检查服务的状态,如果服务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"
lc。

1
引号中是否包含“ SCardSvr”?我不认为应该是,
LittleBobbyTables-Au Revoir,2010年

@LittleBobbyTables:你是对的。没有引号使它起作用。我很傻:-| 谢谢您的帮助
香茅油10/07/24

@Mark好注意。我想您必须用目标操作系统语言需要的任何字符串替换该字符串。我也假设“正在运行”。
lc。

34

要切换服务,请使用以下内容;

NET START“分布式事务处理协调器” || NET STOP“分布式事务处理协调器”


1
它之所以有效是因为从一开始就存在退出代码。如果start命令失败,则可能是因为它已经在运行(并且随后停止它的任何一种方式都不会造成伤害),因此您尝试将其停止。
lc。

3
该命令的结构使得如果net start失败,则它将停止它(由于||表示否则),但是如果net start运行,则net stop将不会执行。辉煌!
DOS医生2012年

1
我认为这是最好的答案,也许@citronas应该考虑将其标记为公认的答案:简单,智能,优雅,并且适合StackOverflow之类的网站。简单点!
Sopalajo de Arrierez

2
为了不被挑剔(好吧,也许只是一点点),但||实际上是一个OR运营商,尽管在这种情况下,它在功能上ELSE发言。这是一个细微但重要的区别。仍然得到+1-我一直在Unix / Linux shell脚本中这样做,不知道为什么我从没想过要在Windows批处理中这样做。
Doug R.

这似乎过分地简化了。我从不希望将它用于自动化处理批处理或供其他人使用的东西……但这正是医生订购的快速图标,我可以将其放置在自己的桌面上以提供我需要的服务时不时地快速切换。
Joel Coehoorn

19

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

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

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

STATE                       : 4 RUNNING

如果停止,我将得到:

STATE                       : 1 STOPPED

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

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


1
感谢您的帮助,同时尝试整合您发布的内容,我大大提高了我的批处理技能;)
citronas 2010年


10

语言独立版本。

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

是的 “太空”总是突然打在你的背上!
Dr.eel

2
几乎完美的答案。我将修复此行:净开始“%ServiceName%”> nul ||(
Cesar

我已经使脚本具有通用性,因此它允许我在Windows Scheduler任务中使用。只需将其替换Set ServiceName=JenkinsSet ServiceName=%~1并称呼它即可watch-service.bat "Jenkins"
Dr.eel'Yan

@ Ant_222它使用'queryex'而不是取决于语言的'query'。以及为什么您认为它不是Windows批处理?您是否尝试过使用它?
Dr.eel

5

我只是找到了该线程,并且如果该人员不想使用批处理文件来重新启动服务,则想添加到讨论中。在Windows中,如果您转到服务,服务属性,然后进行恢复,则有一个选项。您可以在此处设置服务的参数。喜欢在服务停止时重新启动服务。另外,您甚至可以再次尝试失败,做一些与重新启动计算机不同的操作。


2
这是一个有用的答案,但是要注意,这只有在服务已通过exit(-1)停止的情况下才有效。如果服务正常退出(即使出现错误消息),将不会触发自动恢复。如果该服务被用户手动杀死,它也不会触发。
Art Gertner

@sagelightning:我们需要管理员权限才能尝试这种方式。
库马尔M

@ArtGertner-终止(通过任务管理器)服务进程将被解释为“崩溃”并触发恢复。
马丁·巴

3

cuando se使用Windows enEspañol,elcódigodebe 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服务于海上维修服务。维也纳市政总局。(将MYSERVICE替换为要处理的服务的名称。您可以在服务属性上看到服务的名称。)


10
如果您用英语写答案,对每个人都会更好。
2012年

2
不知道为什么要投票。这是重要的一点,也是尽可能避免字符串比较的原因。在这种情况下,您必须根据目标Windows安装的默认语言来更改字符串。
lc。

2
@lc:包含每种语言的答案是否合理?引用(或包括)说出要搜索给定语言的字符串的资源可能更有用。
Mike Bailey 2013年

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

对于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
)

1

如果该服务是以这种方式启动的,我还希望发送一封电子邮件,因此在@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.
      )
    )

  )
)

1

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

开始停止服务

在任务计划程序中,如果要在服务器上使用它,则在参数中使用此

-noprofile -executionpolicy旁路-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
}
}

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

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

0

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

@for /f "tokens=1,* delims=: " %%a in ('sc queryex state=Inactive') do net start "%%b"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.