使用Git Bash / MINGW64和Go在Windows上捕获CTRL-C

时间:2016-08-08 08:33:29

标签: bash go mingw git-bash

我希望在用户点击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中有陷阱&#39; SIGINT):

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

执行cleanup()代码。

MINGW64的输出(也有陷阱&#39;&〜/ .bashrc中的SIGINT):

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

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

1 个答案:

答案 0 :(得分:4)

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

$ winpty ./my-program.exe