如何在不破坏主脚本的情况下使用 Ctrl+C 停止子进程并将子进程输出流式传输到 PowerShell 中的主脚本?

How to stop a child process with Ctrl+C without breaking the main script and stream child output to the main script in PowerShell?

我正在编写 运行正在 Linux 上运行的 powershell 脚本。此脚本的目的是 运行 MS SQL 服务器并显示其输出,但是当用户按下 Ctrl+C 或发生某些错误,脚本获取数据文件夹的副本,然后退出。

[CmdletBinding()]
PARAM (
    [Parameter(ValueFromPipelineByPropertyName)]
    [string] $Command,

    [Parameter(ValueFromPipelineByPropertyName)]
    [string] $Args
)
BEGIN {
    Write-Output "started $PSScriptRoot"
    $currentErrorLevel = $ErrorActionPreference
    # [console]::TreatControlCAsInput = $true
}
PROCESS {

    try {
        $ErrorActionPreference = 'SilentlyContinue';
        $IsSqlRunning = Get-Process -name "sqlservr";

        if ($null -eq $IsSqlRunning) {
            start-process "/opt/mssql/bin/sqlservr" -wait -NoNewWindow
        }
    }
    catch {
        $ErrorActionPreference = $currentErrorLevel;
        Write-Error $_.Exception
    }

}
End {
    $ErrorActionPreference = $currentErrorLevel;
    #do backup
    Create-Backup "/opt/mssql/bin/data"
    Write-Output "finishd!"
}

这个脚本有几个问题:

所以我的首选解决方案是 运行 带有 -Wait 参数的 sql 并防止 powershell 在我按下 Ctrl[=33= 后退出代码]+C,而是 Ctrl+C 关闭 sql 实例

所以我正在寻找一种方法来实现两者。

为简单起见,我假设您的函数只需要支持一个 单个 输入对象,因此我使用的是一个没有 begin 的简单函数体,processend 块,相当于 只是 一个 end 块:

[CmdletBinding()]
PARAM (
    [Parameter(ValueFromPipelineByPropertyName)]
    [string] $Command,

    [Parameter(ValueFromPipelineByPropertyName)]
    [string] $Args
)
    Write-Output "started $PSScriptRoot"

    # No need to save the current value, because the modified
    # value is local to the function and goes out of scope on 
    # exiting the function.
    $ErrorActionPreference = 'SilentlyContinue';

    try {
        $IsSqlRunning = Get-Process -name "sqlservr";

        if ($null -eq $IsSqlRunning) {
            start-process "/opt/mssql/bin/sqlservr" -wait -NoNewWindow
        }
    }
    catch {
        Write-Error $_.Exception
    }
    finally {

      # This block is *always* called - even if Ctrl-C was used.

      Create-Backup "/opt/mssql/bin/data"
      # CAVEAT: If Ctrl-C was used to terminate the run, 
      #         you can no longer produce *pipeline* input at this point
      #         (it will be quietly ignored).
      #         However, you can still output to the *host*.
      Write-Host "finished!"

    }

如果你真的需要支持多个输入对象,它会变得更复杂。