英文:
do actions on end of execution
问题
我有一个http服务器(使用http.Handle
启动),我想要进行一些操作。
我该如何在Linux上进行这些操作?在按下ctrl-C的情况下,是否可以执行这些操作?
我对Unix信号不熟悉,所以答案可能很简单。
英文:
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
得分: 24
使用kostix的答案,我构建了这段代码(现在适应Go1),以捕获中断信号并在退出之前执行一些操作:
go func() {
sigchan := make(chan os.Signal)
signal.Notify(sigchan, os.Interrupt)
<-sigchan
log.Println("程序被终止!")
// 执行最后的操作并等待所有写操作结束
os.Exit(0)
}()
// 开始主程序任务
英文:
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)
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
答案2
得分: 4
你可以使用signal包订阅TERM和INT信号。但请注意,这些信号只在进程被显式地终止时发送;正常退出(由进程自身发起)不涉及任何信号。我认为对于正常退出,只需在主例程中执行一些操作(假设应该生成工作协程,然后等待它们)。
阅读man 7 signal
以获取有关POSIX信号的更一般信息。
英文:
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.
答案3
得分: 4
我假设作者不仅对<kbd>Ctrl+C</kbd>感兴趣,还为Linux提供了更广泛的解决方案(有关Windows信号,请参阅x/sys/windows):
<!-- language: lang-go -->
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, // “正常请求程序终止的方式”
syscall.SIGINT, // Ctrl+C
syscall.SIGQUIT, // Ctrl-\
syscall.SIGKILL, // “始终致命”,“SIGKILL和SIGSTOP可能无法被程序捕获”
syscall.SIGHUP, // “终端断开连接”
)
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
// 所有主要的延迟函数都在这里执行,即使发生恐慌也是如此。
// 非主要的延迟函数不会在这里执行。
}
P.S. 没有信号处理os.Exit
。
通过这个配置,在<kbd>Ctrl+C</kbd>或接收到其他信号时,程序将把os.Signal
推入通道exitChan
,这将解除<-exitChan
操作的阻塞,main
函数将继续执行最后的代码行,然后返回,然后执行延迟函数。
非主要的延迟函数
对于非主要的延迟函数,您可以:
- 使用https://github.com/tebeka/atexit
- 将重要资源移入全局数组,并在主要延迟函数中释放它们。如果您不使用事务,则此解决方案不完美:1)创建资源,2)添加到数组中,-- 这个过程不应该被退出中断。我猜测对切片的非并发读写访问也必须提供。
英文:
I suppose author is interested not only in <kbd>Ctrl+C</kbd> and offer more broad solution for Linux (for Windows signals see x/sys/windows):
<!-- language: lang-go -->
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 <kbd>Ctrl+C</kbd> 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论