在 Powershell 中优雅地停止

Posted

技术标签:

【中文标题】在 Powershell 中优雅地停止【英文标题】:Gracefully stopping in Powershell 【发布时间】:2010-12-15 04:56:08 【问题描述】:

如何在 PowerShell 脚本中捕获和处理 Ctrl+C?我知道我可以从 v2 中的 cmdlet 执行此操作,方法是包含 Powershell.Stop() 方法的覆盖,但我找不到在脚本中使用的模拟。

我目前正在执行清理via an end block,但是当脚本被取消时我需要执行额外的工作(而不是运行到完成)。

【问题讨论】:

Is there a way to catch ctrl-c and ask the user to confirm?的可能重复 【参考方案1】:

您可以使用here on PoshCode中描述的方法

总结:

设置

[console]::TreatControlCAsInput = $true

然后使用

轮询用户输入
if($Host.UI.RawUI.KeyAvailable -and (3 -eq  
    [int]$Host.UI.RawUI.ReadKey("AllowCtrlC,IncludeKeyUp,NoEcho").Character))

【讨论】:

哇,太疯狂了。我最终只是将我的脚本重写为 C# 中的 cmdlet,这样我就可以覆盖 Stop()。【参考方案2】:

try-catch-finally 的 documentation 说:

即使您使用 CTRL+C 停止脚本,Finally 块也会运行。最后 如果 Exit 关键字从 Catch 中停止脚本,块也会运行 块。

请参阅以下示例。运行它并按ctrl-c 取消它。

try

    while($true)
    
        "Working.."
        Start-Sleep -Seconds 1
    

finally

    write-host "Ended work."

【讨论】:

这是真的,但最终会运行不仅因为 Exit 被调用,而且如果 Try 块成功。正如我在问题中指出的那样,当脚本被取消(而不是运行到完成)时,我需要执行额外的工作。 @fatcat111 使用布尔标志。例如,在try 的末尾设置$didcomplete = $true 并在finally 内使用if ($didcomplete) Write-Host "Ended work." 进行检查 很遗憾,如果关闭 PowerShell 控制台窗口,finally 块不会执行。 在停止远程 PSSession 调用命令或作业时也会调用 finally 块!【参考方案3】:

$PSCmdlet 上还有一个 Stopping 属性可用于此目的。

【讨论】:

Stoppingfalse,即使在按 PowerShell/PowerShell#6322 停止时也是如此。【参考方案4】:

这是最近的工作解决方案。我在需要控制执行中断(关闭文件句柄)的循环中使用 if 部分。

    [Console]::TreatControlCAsInput = $true # at beginning of script

    if ([Console]::KeyAvailable)

        $readkey = [Console]::ReadKey($true)

        if ($readkey.Modifiers -eq "Control" -and $readkey.Key -eq "C")                
            # tasks before exit here...
            return
        

    

另请注意,有一个错误导致 KeyAvailable 在脚本启动时为真。您可以通过在开始时读取调用 ReadKey 来缓解。这种方法不需要,只是在这种情况下值得了解。

【讨论】:

以上是关于在 Powershell 中优雅地停止的主要内容,如果未能解决你的问题,请参考以下文章

Kubernetes 中如何保证优雅地停止 Pod

Kubernetes 中如何保证优雅地停止 Pod

如何优雅地停止长时间执行的线程?

优雅地停止 ecs 容器

如何优雅地停止 uWebSockets 服务器?

优雅地关闭节点实例,不中途停止任何事情