在执行结束时执行操作

Den*_*ret 6 signals interrupt go

我有一个http服务器(使用启动http.Handle),我想做一些操作.

我怎么能这样做(在linux上)?在ctrl-C的情况下是否可以执行这些操作?

我不熟悉unix信号所以答案可能微不足道.

Den*_*ret 17

使用kostix答案,我构建了这个代码(现在适用于Go1)来捕获中断信号并在退出之前执行一些操作:

go func() {
    sigchan := make(chan os.Signal, 10)
    signal.Notify(sigchan, os.Interrupt)
    <-sigchan
    log.Println("Program killed !")

    // do last actions and wait for all write operations to end

    os.Exit(0)
}()

// start main program tasks
Run Code Online (Sandbox Code Playgroud)


ily*_*rov 5

我想作者不仅对 Linux 感兴趣Ctrl+C,而且还为 Linux 提供了更广泛的解决方案(对于 Windows 信号,请参阅x/sys/windows):

package main

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

func getFireSignalsChannel() chan os.Signal {

  c := make(chan os.Signal, 1)
  signal.Notify(c,
    // https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html
    syscall.SIGTERM, // "the normal way to politely ask a program to terminate"
    syscall.SIGINT, // Ctrl+C
    syscall.SIGQUIT, // Ctrl-\
    syscall.SIGKILL, // "always fatal", "SIGKILL and SIGSTOP may not be caught by a program"
    syscall.SIGHUP, // "terminal is disconnected"
  )
  return c

}

func exit() {
  syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
}

func main() {

  exitChan := getFireSignalsChannel()
  input, err := os.Open("input.txt")
  if err != nil {
    panic(err)
  }
  defer input.Close()
  <-exitChan
  fmt.Println("Exiting!")
  return
  // All main deferreds executed here even in case of panic.
  // Non-main deferreds are not executed here.

}
Run Code Online (Sandbox Code Playgroud)

PS 没有信号处理os.Exit

通过此配置Ctrl+C或接收其他信号,程序将推os.Signal入通道,exitChan该通道将解除阻塞<-exitChan操作main,并且该函数将在最后几行继续执行,然后返回,然后执行延迟函数。

非主要延期

对于非主要延期,您可以:

  1. 使用https://github.com/tebeka/atexit
  2. 将重要资源移入全局数组并在主延迟中释放它们。如果您不使用事务,则此解决方案并不完美:1)创建资源,2)添加到数组,--不应因退出而中断。我猜还必须提供对切片的非并发读写访问。


kos*_*tix 4

您可以使用信号包订阅 TERM 和 INT 信号。但请注意,这些信号仅在进程被显式终止时才会发送;正常退出(由进程本身启动)不涉及任何类型的信号。我认为对于正常退出,只需在主例程中执行一些操作(据说应该生成工作协程然后等待它们)。

阅读man 7 signal有关 POSIX 信号的更多一般信息。