17

我们正在使用 stop-service cmdlet 来终止我们机器上的一些服务。大多数情况下它运行良好,但是我们有一两个服务(谁没有?)偶尔表现不佳。

在这种情况下,有问题的服务之一将保持停止状态,并且 cmdlet 一遍又一遍地将其输出到控制台:

[08:49:21]WARNING: Waiting for service 'MisbehavingService (MisbehavingService)' to finish 
[08:49:21]stopping...
[08:49:23]WARNING: Waiting for service 'MisbehavingService (MisbehavingService)' to finish 
[08:49:23]stopping... 
[08:49:25]WARNING: Waiting for service 'MisbehavingService (MisbehavingService)' to finish 
[08:49:25]stopping...

最终我们必须在任务管理器中终止服务,然后我们的脚本继续。

有没有办法让 stop-service cmdlet 在某个点之后放弃或超时?我想我们可以事后检查,如果服务仍在运行,请使用 kill-process cmdlet 提供最终结果。

4

3 回答 3

19

虽然Stop-Service没有超时参数,但类WaitForStatus上的方法System.ServiceController确实有一个带超时参数的重载(在此处记录)。幸运的是,这正是Get-Service命令返回的对象类型。

这是一个简单的函数,它接受服务名称和超时(以秒为单位)。$true如果服务在达到超时之前停止,并且$false调用超时(或者如果服务不存在) ,它将返回。

function Stop-ServiceWithTimeout ([string] $name, [int] $timeoutSeconds) {
    $timespan = New-Object -TypeName System.Timespan -ArgumentList 0,0,$timeoutSeconds
    $svc = Get-Service -Name $name
    if ($svc -eq $null) { return $false }
    if ($svc.Status -eq [ServiceProcess.ServiceControllerStatus]::Stopped) { return $true }
    $svc.Stop()
    try {
        $svc.WaitForStatus([ServiceProcess.ServiceControllerStatus]::Stopped, $timespan)
    }
    catch [ServiceProcess.TimeoutException] {
        Write-Verbose "Timeout stopping service $($svc.Name)"
        return $false
    }
    return $true
}
于 2016-03-08T15:44:33.773 回答
7

stop-service 没有超时选项,但是如果有依赖的服务,可能需要使用-force。

服务启动时可以定义等待提示(指定超时),但超时由服务控制。任何服务控制请求(启动、停止、暂停、恢复)都会通过服务控制管理器 (SCM) 并尊重每个服务的等待提示。如果超过等待提示,操作将失败并返回错误。

您可以使用 invoke-command 将 Stop-Service 作为作业运行并定期检查。如果尚未完成,您可以使用 Stop-Process 终止该进程并继续。

于 2012-09-21T16:33:09.250 回答
1

如果你有 powershell 5.1,你还有:

Stop-Service -Name "NameOfService" -NoWait

https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.management/stop-service

但是,如果您没有 5.1 版本的 powershell,@JamesQMurphy 的答案看起来也不错。

于 2017-05-24T18:06:33.743 回答