在服务停止完成之前暂停批处理文件?
Posted
技术标签:
【中文标题】在服务停止完成之前暂停批处理文件?【英文标题】:Halt batch file until service stop is complete? 【发布时间】:2010-05-20 14:54:27 【问题描述】:我正在使用批处理文件来停止 Windows 服务。我正在使用sc
命令,但鉴于以下问题,我对其他想法持开放态度。问题是批处理文件继续而服务正在停止(sc
的stop
参数似乎只是请求停止 - 它没有等待停止)。
如何将批处理文件修改为不继续直到停止完成?
【问题讨论】:
【参考方案1】:您可以使用NET stop
,它是同步的,即它会一直等到服务停止。
看 - NET stop
【讨论】:
但是,如果服务已经停止,net stop
将抛出一般错误代码 2(拒绝访问)。
这并不完全正确。如果服务需要 4 分钟才能真正完全停止并退出,“net stop”命令将在 20-40 秒后返回,但服务进程尚未终止。它返回“无法停止服务”......但这具有误导性。服务已被发送停止命令,但在 SCM 超时内还没有完全退出。
我知道这个线程很旧,但我刚刚在 Windows Server 2012 R2 上测试了这个 - 我有一个服务,它需要大约三分钟才能停止......当运行“net stop”时,命令不会' t 在 CMD 文件完成之前,服务可执行文件实际停止并从任务管理器中消失。它可以在更新的服务器上运行,而一些较旧的 cmets 说它不能。
net stop
返回后,如果使用sc query "My Service Name" | find "STATE"
查看状态,部分服务可能处于STOP_PENDING
状态【参考方案2】:
sc stop webdriveservice
:loop
sc query webdriveservice | find "STOPPED"
if errorlevel 1 (
timeout 1
goto loop
)
【讨论】:
优秀的答案。只是一个问题:为什么是 TIMEOUT 而不是 SLEEP? TIMEOUT 会被按键绕过,我认为这在批处理文件中并不是一个理想的效果(在专注于 cmd 窗口时很容易误按一个键)。 实际上,它是 2003 Resource Kit 的一部分。我以为它是在标准的 Windows 安装中,我的错。timeout 5 /nobreak
将仅在 CTRL+C 时退出【参考方案3】:
如上所述,NET STOP 会向服务发送停止命令,但是,如果服务花费的时间超过一定时间(我的观察是 20 秒左右),NET STOP 不会等待服务实际停止在返回之前。
要真正暂停批处理文件直到服务停止,您需要使用类似于这些线程中概述的方法:
How to check if a service is running via batch file and start it, if it is not running?
Stopping/Starting a remote Windows service and waiting for it to open/close
【讨论】:
不是反对者(虽然我可以猜到是谁),但这个答案也包含错误信息。NET STOP
将等待服务停止,直到某个点。我从来没有让服务尝试停止整整四分钟,所以我不能说NET STOP
等待了多长时间,但它确实等待了相当长的一段时间,而不是@987654326 @.\
@LittleBobbyTables 该帖子已更新以说明您观察到的情况。如果您查看 microsoft 团队编写的内容(下面的链接),您会发现 SCM 一次只与一项服务对话,因此它不会永远等待任何一项服务。 NET SEND 只是向 SCM 发送 cmd 的一种方式,与服务管理器中的相同。 blogs.msdn.com/b/bclteam/archive/2009/02/19/…
从@Jonesome 链接的博客中提取更多信息:控制超时的注册表项是HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\WaitToKillServiceTimeout
。默认值显然是 20 秒,但在我的 Windows 8.1 Enterprise 机器上是 5 秒(可能会被组策略更改)。
@Stajs on Windows 2012 我将我的HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\WaitToKillServiceTimeout
设置为 DWORD 120000 并且它完全没有效果 - 即使服务正在关闭但没有停止,网络停止仍然在 10-15 秒后返回,不会再停 45 秒【参考方案4】:
我认为net stop [Service]
应该等到服务完全停止后再继续。 sc stop [Service]
只是向服务发送“停止”消息。
【讨论】:
@Jonesome - 与其投反对票,不如提供一个更好的答案? 公平通话!完毕!投反对票的原因是两个答案都包含错误的信息(我在 win7 和 win2008 上进行了测试,并且根据经验知道 XP 和其他版本的行为相同)。【参考方案5】:net stop
也有类似的问题。它在服务确实停止时返回,但可执行文件可能仍在运行。
由于升级原因,这还不够好,我们需要等到过程完成。
我使用了一个简单的循环来等待服务可执行文件实际完成:
net stop "ServiceName"
:loop1
set _CmdResult=""
for /f "tokens=1" %%a in ('TASKLIST ^| FINDSTR ServiceName.exe') do set _CmdResult=%%a
if not %_CmdResult% == "" (
timeout 5
goto loop1
)
一旦可执行文件完成,循环就会中断。
【讨论】:
【参考方案6】:这有点粗略,但它对我有用,以确保我可以安排每日批处理文件来实质上重新启动服务。
NET STOP [服务]
:再试一次
超时 /T 10 /NOBREAK
NET START [服务]
IF %ERRORLEVEL% NEQ 0 GOTO TryAgain
我通过这段代码 sn-p 意识到,如果服务无法成功启动,这可能会导致无限循环。我只是想基本上展示如何使用 TIMEOUT 来解决这个问题,其中服务可能需要比 NET STOP 命令允许的时间更长的时间才能停止。
【讨论】:
【参考方案7】:在命令之间使用&&
符号。 &&
符号等待完成前一个命令,然后再继续执行下一个命令。
所有命令必须位于同一命令行。您可以连续使用任意数量的命令。
您也可以使用pause
命令。这样,在进行下一个过程之前,要求按任意键。
例如:
sc qdescription "MyServiceName" && echo. && sc stop "MyServiceName" && echo. && echo [ "MyServiceName" service stopped ] && echo. && pause
【讨论】:
以上是关于在服务停止完成之前暂停批处理文件?的主要内容,如果未能解决你的问题,请参考以下文章