检查 Windows 服务列表是不是正在运行,如果不是从批处理文件启动
Posted
技术标签:
【中文标题】检查 Windows 服务列表是不是正在运行,如果不是从批处理文件启动【英文标题】:check if a list of windows services are running and start if not from batch file检查 Windows 服务列表是否正在运行,如果不是从批处理文件启动 【发布时间】:2021-06-26 09:12:26 【问题描述】:我正在寻找一个批处理脚本来检查是否有一些服务正在运行,如果没有启动它们,这就是我到目前为止检查特定服务是否正在运行的内容:
for /F "tokens=3 delims=: " %%H in ('sc query "service1" ^| findstr " STATE"') do (
if /I "%%H" NEQ "RUNNING" (
net start "service1"
)
但是,我想修改这个 for 循环以检查是否有其他服务的匹配项,例如“service2”、“service3”、“service4”和“service5”,但我不知道该怎么做.是否可以将这些匹配项包含在同一个 For 循环中?
谢谢
【问题讨论】:
不是检查字符串RUNNING
那么简单。一个服务,如果启动了,可以有多个状态,仅仅因为状态不是RUNNING
,并不代表它可以启动。状态可以是Stopped
、Start Pending
、Stop Pending
、Running
、Continue Pending
、Pause Pending
、Paused
和 Unknown
。无论如何,我不确定如果您要求启动已在运行的服务会发生什么,但我假设可能只是一条错误消息,(您可以发送到NUL
)。那么为什么不尝试启动所有这些,看看会发生什么。使用sc start
,而不是net start
【参考方案1】:
这是一个你可能没有考虑过的替代方案,(忽略了我之前评论中的建议),它可以直接在 cmd 中运行,或者从 batch-file 中运行:
%SystemRoot%\System32\wbem\WMIC.exe Service Where "Name='Service1' Or Name='Service2' Or Name='Service3' Or Name='Service4 Or Name='Service5 And Started='TRUE' And State !='Running'" Call StartService >NUL 2>&1
您需要自己决定是否需要 Started='TRUE'
部分,但我建议您首先一定要保留它。
【讨论】:
我试试看是否需要相应地调整“开始”标志,谢谢【参考方案2】:如果您想在一个循环中使用 FOR 批量执行此操作:
FOR /F "tokens=2,3 delims=: " %%H IN ('^(SC QUERY "Service1" ^& SC QUERY "Service2"^) ^| FINDSTR /C:"SERVICE_NAME" /C:" STATE" ') DO (IF NOT "%%H" == "" (IF "%%I" == "" SET LOCALV_SERV=%%H) & IF NOT "%%I" == "" (IF /I "%%I" NEQ "RUNNING" CALL NET START %%LOCALV_SERV%%))
我们通过连接多个 SC 输出一次查询多个服务,然后在这里使用 FINDSTR 功能一次搜索多个字符串以获得服务名称和服务状态。
按照@Compo 的建议,您应该测试许多其他服务状态。
那么对于您的用例,命令应该是:
FOR /F "tokens=2,3 delims=: " %%H IN ('^(SC QUERY "Service1" ^& SC QUERY "Service2" ^& SC QUERY "Service3" ^& SC QUERY "Service4" ^& SC QUERY "Service5"^) ^| FINDSTR /C:"SERVICE_NAME" /C:" STATE" ') DO (IF NOT "%%H" == "" (IF "%%I" == "" SET LOCALV_SERV=%%H) & IF NOT "%%I" == "" (IF /I "%%I" NEQ "RUNNING" CALL NET START %%LOCALV_SERV%%))
将 Service1、Service2、Service3、Service4、Service5 替换为您要定位的服务名称。
由于@Compo 指出使用 CALL 进行延迟扩展可能不合适,因此这里是显式启用延迟扩展的相同脚本:
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F "tokens=2,3 delims=: " %%H IN ('^(SC QUERY "Service1" ^& SC QUERY "Service2"^) ^| FINDSTR /C:"SERVICE_NAME" /C:" STATE" ') DO (IF NOT "%%H" == "" (IF "%%I" == "" SET LOCALV_SERV=%%H) & IF NOT "%%I" == "" (IF /I "%%I" NEQ "RUNNING" NET START !LOCALV_SERV!))
这是我的答案的扩展,基于 cmets,它仅在循环内需要的地方启用延迟扩展。这个版本还去掉了对%PATH%
、%PATHEXT%
的依赖,提高了可读性:
@Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "SC=%SystemRoot%\System32\sc.exe"
Set "FS=%SystemRoot%\System32\findstr.exe"
For /F "Tokens=2-3 Delims=: " %%G In ('
(%SC% Query "Service1" ^&
%SC% Query "Service2" ^&
%SC% Query "Service3" ^&
%SC% Query "Service4" ^&
%SC% Query "Service5"^) 2^>NUL
^| %FS% /BIC:"SERVICE_NAME:" /C:" STATE "
') DO (
If Not "%%G" == "" If "%%H" == "" Set "LOCALV_SERV=%%G"
If Not "%%H" == "" If /I Not "%%H" == "RUNNING" (
SetLocal EnableDelayedExpansion
%SC% Start !LOCALV_SERV!
EndLocal
)
)
【讨论】:
谢谢,请问 service1 和 service2 是什么,以便我可以确定是否需要在我的用例中添加 3,4 和 5?我可以安全地假设我可以将我的字符串匹配附加到 FINDSTR,有点像这样 'FINDSTR /C:"service1" /C:"service2" ? @user1283674 您不需要更改 FINDSTR,它会从 sc 输出中自行获取服务名称。如果您有 5 个服务要检查,只需将SC QUERY "Service1" ^& SC QUERY "Service2"
更改为 SC QUERY "Service1" ^& SC QUERY "Service2" ^& SC QUERY "Service3" ^& SC QUERY "Service4" ^& SC QUERY "Service5"
明白了,感谢您的宝贵时间
我认为在另一个 cmd.exe
实例中运行多个 sc.exe
命令和一个 findstr.exe
没有任何好处,然后是一系列 if
命令和一个 net.exe
命令, 做一个WMIC.exe
命令可以做的事情。还有为什么要使用不同的可执行文件net.exe
,当你已经使用sc.exe
,并且已经可以start
一个服务。此外,net.exe
不是批处理文件,如果您查看Call
命令的帮助信息,(命令提示符窗口中的call /?
),您应该注意在这种情况下,Call
不是必需的或不需要的。
是的 Zilog80,我希望你不介意,但我添加了一个额外的示例,仅在需要的地方延迟扩展,在循环中,你的答案。我也赞成它,因为虽然它的效率较低,但从技术上讲,它是对特定问题的直接回答。以上是关于检查 Windows 服务列表是不是正在运行,如果不是从批处理文件启动的主要内容,如果未能解决你的问题,请参考以下文章
如何通过批处理文件检查服务是不是正在运行并启动它,如果它没有运行?