Stop-Service Cmdlet 超时可能吗?

19
我们正在使用stop-service命令在我们的服务器上停止几个服务。大多数情况下它运行得很好,但是有一两个服务(谁没有呢?)偶尔不太友好。
在这种情况下,其中一个相关的服务将保持在停止状态,而该命令会一遍又一遍地将其输出到控制台中:
[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命令在一定时间后放弃或超时?我认为我们之后可以检查一下,如果服务仍在运行,则使用kill-process命令来进行最终处理。

3个回答

23
尽管 Stop-Service 命令没有超时参数,但是 System.ServiceController 类上的 WaitForStatus 方法有一个重载,它接受一个超时参数(文档记录在这里)。幸运的是,这正是 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
}

7

停止服务时没有超时选项,但如果有依赖服务,您可能需要使用-force参数。

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

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


谢谢Steven。我认为下面的讨论也提供了一些关于这个主题的好建议。特别是页面上的最后一个帖子:http://www.powershellcommunity.org/Forums/tabid/54/aft/5243/Default.aspx - larryq

2

3
答案没有回答问题,该问题要求在一定时间后“放弃”或超时。异步终止和等待超时不是同一回事。 - Cardin
1
我认为这是一个更简单实现停止服务和等待模式的建议,与JamesQMurphy提出的相似。 - ojintoad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接