问题
I have an http server (launched using http.Handle
) and I would like to do some operations.
How can I do that (on linux) ? Is it possible to do those operations in case of a ctrl-C ?
I'm not familiar with unix signals so the answer may be trivial.
回答1:
You can subscribe to the TERM and INT signals using the signal package. But note that these signals are only sent when the process is killed explicitly; normal exit (initiated by the process itself) does not involve any sort of signals. I think for normal exit just do something in the main routine (which supposedly should spawn worker goroutines and then wait on them).
Read man 7 signal
for more general info on POSIX signals.
回答2:
Using kostix answer, I built this code (now adapted to Go1) to catch the interrupt signal and do some operations before exiting :
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
回答3:
I suppose author is interested not only in Ctrl+C and offer more broad solution for Linux (for Windows signals see 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.
}
P.S. None of signals handles os.Exit
.
With this configuration on Ctrl+C or on receiving other signal program will push os.Signal
into channel exitChan
which will unblock <-exitChan
operation and the main
function will continue execution on the final lines, then return, then execute deferred functions.
Non-Main Deferreds
For non-main deferred you may:
- Use https://github.com/tebeka/atexit
- Move important resources into global array and release them in a main deferred. This solution is not perfect if you don't use transaction: 1) create resource, 2) add to array, -- which shouldn't be interrupted by exit. Also non-concurrent read-write access to a slice must be provided I guess.
来源:https://stackoverflow.com/questions/8403862/do-actions-on-end-of-execution