英文:
Go signal handler doesn't handle terminal window closing
问题
我用Go语言编写了一个命令行工具。当通过终端调用该命令行工具时,我希望工具在调用cleanup()函数之前等待Ctrl+C中断(SIGINT),最后退出。
然而,除了处理SIGINT之外,我还希望该工具能处理用户简单关闭终端窗口的情况。如果窗口关闭,我希望调用相同的cleanup函数。以下是我尝试的示例代码。
package main
import (
"fmt"
"os"
"syscall"
"os/signal"
"os/exec"
"github.com/sirupsen/logrus"
)
func main() {
// 解析命令行参数
if len(os.Args) < 2 {
logrus.Fatalf("缺少必需的参数")
}
arg := os.Args[1]
logrus.Infof("使用参数运行:%s", arg)
// 设置信号处理
signals := make(chan os.Signal, 1)
signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT)
done := make(chan bool, 1)
go func() {
sig := <-signals
fmt.Println("")
fmt.Println("通过Ctrl+C请求断开连接", sig)
done <- true
}()
logrus.Infof("按下Ctrl+C断开连接。")
<-done
cleanup()
os.Exit(0)
}
func cleanup() {
fmt.Println("执行清理任务...")
touchFile := exec.Command("touch", "testfile.txt")
_, err := touchFile.CombinedOutput()
if err != nil {
println(err)
}
}
这段代码可以处理用户通过Ctrl+C发送中断信号的情况,并调用cleanup函数,但是当用户简单关闭窗口时,cleanup函数不会被调用。我认为包含syscall.SIGHUP
应该可以解决这个问题。请指导。
编辑:我在默认的MacOS终端中测试了这段代码,在关闭窗口时会调用cleanup函数,但在使用iTerm时不会调用。
英文:
I have written a cli tool in go. When the cli tool is invoked via the terminal, i want the tool to wait for a Ctrl+C interrupt(SIGINT) before calling a cleanup() function, before finally exiting.
however, as well as handling SIGINT, i also want the tool to handle cases where the terminal window is simply closed by the user. if its closed, i want the same cleanup function to be called. Here is a sample of what i tried.
package main
import (
"fmt"
"os"
"syscall"
"os/signal"
"os/exec"
"github.com/sirupsen/logrus"
)
func main() {
// Parse the command-line argument.
if len(os.Args) < 2 {
logrus.Fatalf("Missing required argument")
}
arg := os.Args[1]
logrus.Infof("Running with argument: %s", arg)
// Set up signal handling.
signals := make(chan os.Signal, 1)
signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT)
done := make(chan bool, 1)
go func() {
sig := <-signals
fmt.Println("")
fmt.Println("Disconnection requested via Ctrl+C", sig)
done <- true
}()
logrus.Infof("Press Ctrl+C to disconnect.")
<-done
cleanup()
os.Exit(0)
}
func cleanup() {
fmt.Println("Performing cleanup tasks...")
touchFile := exec.Command("touch", "testfile.txt",)
_, err := touchFile.CombinedOutput()
if err != nil {
println(err)
}
}
This works for cases where the user sends an interrupt via Ctrl+C and the cleanup function is called, but the cleanup function is never called when the user simply just closes the window. I though the inclusion of syscall.SIGHUP
would work for this. please advise.
Edit: i've tested this in the default MacOS terminal, and the cleanup function is called when closing the window, but not when using iTerm.
答案1
得分: 0
package main
import (
redacted
)
func main() {
// 解析命令行参数。
if len(os.Args) < 2 {
logrus.Fatalf("缺少必需的参数")
}
arg := os.Args[1]
log.Infof("使用参数运行: %s", arg)
// 设置信号处理。
signals := make(chan os.Signal, 1)
signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT)
done := make(chan bool, 1)
go func() {
sig := <-signals
fmt.Println("")
fmt.Println("通过 Ctrl+C 请求断开连接", sig)
done <- true
}()
log.Infof("按下 Ctrl+C 断开连接。")
<-done
cleanup()
os.Exit(0)
}
func cleanup() {
fmt.Println("执行清理任务...")
touchFile := exec.Command("touch", "testfile.txt")
_, err := touchFile.CombinedOutput()
if err != nil {
println(err)
}
}
现在在 iTerm 中添加了 SIGKILL 的功能。
英文:
package main
import (
redacted
)
func main() {
// Parse the command-line argument.
if len(os.Args) < 2 {
logrus.Fatalf("Missing required argument")
}
arg := os.Args[1]
log.Infof("Running with argument: %s", arg)
// Set up signal handling.
signals := make(chan os.Signal, 1)
signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT)
done := make(chan bool, 1)
go func() {
sig := <-signals
fmt.Println("")
fmt.Println("Disconnection requested via Ctrl+C", sig)
done <- true
}()
log.Infof("Press Ctrl+C to disconnect.")
<-done
cleanup()
os.Exit(0)
}
func cleanup() {
fmt.Println("Performing cleanup tasks...")
touchFile := exec.Command("touch", "testfile.txt",)
_, err := touchFile.CombinedOutput()
if err != nil {
println(err)
}
}
The addition of SIGKILL works now for iTerm.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论