【问题标题】:Catch CTRL-C on Windows using Git Bash / MINGW64 with Go使用带有 Go 的 Git Bash / MINGW64 在 Windows 上捕获 CTRL-C
【发布时间】:2016-12-13 22:54:29
【问题描述】:

当用户按下 CTRL-C 时,我想在退出之前运行特定代码。代码在 Go 中,我想使用 Git Bash / MINGW64 在 Windows 上运行它。使用 Go,我愿意

interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
// some goroutines get started here
// ...
for {
  select {
  case <-interrupt:
    // code which shall be run on CTRL-C
  }
}

在 Windows 上,这在我使用 Windows 命令行时有效,但我希望它也能在 MINGW64/Git Bash 上工作。

我在https://stackoverflow.com/a/31974985/1370397 上发现添加

trap '' SIGINT

to ~/.bashrc 捕获 SIGINT 信号并防止 bash 终止我的程序。

这适用于我在带有 bash 版本的 MINGW32 上

$ bash --version
GNU bash, version 3.1.20(4)-release (i686-pc-msys)
Copyright (C) 2005 Free Software Foundation, Inc.

但它无法在 MINGW64,bash 版本上运行

$ bash --version
GNU bash, version 4.3.42(5)-release (x86_64-pc-msys)
Copyright (C) 2013 Free Software Foundation, Inc.
[...]

MINGW64 或新 (git) bash 版本有什么不同?

为了更容易测试,下面是一个查看行为差异的最小示例:

package main

import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
    "time"
)

func cleanup(){
    for i:=0; i<3; i++ {
        fmt.Println("Cleaning up...")
        time.Sleep(500*time.Millisecond)
    }
}

func work() {
    for {
        fmt.Println("Working...")
        time.Sleep(300*time.Millisecond)
    }
}

func main() {
    interrupt := make(chan os.Signal, 1)
    signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)

    go work()

    for {
        select {
        case <-interrupt:
            fmt.Println("Interrupt received - calling cleanup()...")
            cleanup()
            fmt.Println("Quitting...")
            return
        }
        fmt.Println("Waiting...")
    }
}

来自 MINGW32 的输出(在 ~/.bashrc 中带有陷阱 '' SIGINT):

$ ./sigint.exe
Working...
Working...
Working...
Interrupt received - calling cleanup()...
Cleaning up...
Working...
Working...
Cleaning up...
Working...
Cleaning up...
Working...
Working...
Quitting...

cleanup() 代码被执行。

来自 MINGW64 的输出(在 ~/.bashrc 中也带有陷阱 '' SIGINT):

$ ./sigint.exe
Working...
Working...
Working...
Working...

cleanup() 没有被执行。 :-(

【问题讨论】:

  • 这里似乎有人有类似的设置sourceforge.net/p/mingw-w64/bugs/561 可能值得跟进 Keynan Pratt。有人提到它可能是一个 GO 错误。但从你所说的可能它在 MINGW64 中。您或许应该在此处将指针添加回您的帖子。
  • 不是 Go 的错误,实际上,如果你在 C 中尝试同样的方法也会发生。

标签: bash go mingw git-bash


【解决方案1】:

使用winpty 在适用于 Windows 的 Git Bash 中正确捕获信号。它与安装捆绑在一起,因此您需要做的就是:

$ winpty ./my-program.exe

【讨论】:

  • 感谢菲尔的回答。这对我来说很有用。我发现的一件事是,一旦我至少使用了一次winpty,那么程序的后续调用将捕获信号,而无需我显式调用winpty。这正是我想要发生的事情。
  • 所以我做了“winpty mintty”(mintty 是在 Windows 上运行 git bash 窗口的程序)。它提示我选择哪个薄荷版本。它现在似乎仍然为我工作......
猜你喜欢
  • 2019-06-05
  • 1970-01-01
  • 2011-11-22
  • 2011-11-26
  • 2015-11-28
  • 2018-11-17
  • 2021-09-21
  • 2017-12-21
  • 1970-01-01
相关资源
最近更新 更多