Czy można przechwycić sygnał Ctrl + C i uruchomić funkcję czyszczenia, w sposób "odrocz"?
Chcę przechwycić Ctrl + C (SIGINT
) sygnał wysyłany z konsoli i wypisuje częściowe sumy uruchomień.
Uwaga: kiedy po raz pierwszy napisałem pytanie, byłem zdezorientowany, że Ctrl+C jest SIGTERM
zamiast SIGINT
.
9 answers
Możesz użyć pakietu os/signal do obsługi przychodzących sygnałów. ^C to SIGINT , więc możesz użyć tego do pułapki os.Interrupt
.
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func(){
for sig := range c {
// sig is a ^C, handle it
}
}()
Sposób, w jaki spowodujesz zakończenie programu i wydrukowanie informacji, zależy wyłącznie od Ciebie.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-24 20:53:44
To działa:
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
"time" // or "runtime"
)
func cleanup() {
fmt.Println("cleanup")
}
func main() {
c := make(chan os.Signal)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
<-c
cleanup()
os.Exit(1)
}()
for {
fmt.Println("sleeping...")
time.Sleep(10 * time.Second) // or runtime.Gosched() or similar per @misterbee
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-22 23:29:30
Aby dodać nieco do pozostałych odpowiedzi, jeśli rzeczywiście chcesz złapać SIGTERM (domyślny sygnał wysyłany przez polecenie kill), możesz użyć syscall.SIGTERM
zamiast systemu operacyjnego.Przerywam. Uwaga: interfejs syscall jest specyficzny dla systemu i może nie działać wszędzie (np. w systemie windows). Ale fajnie jest złapać oba:
c := make(chan os.Signal, 2)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
....
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-25 19:55:12
W zaakceptowanej odpowiedzi powyżej była (w momencie pisania postu) jedna lub dwie małe literówki, więc oto wersja oczyszczona. W tym przykładzie Zatrzymuję CPU profiler po otrzymaniu Ctrl + C.
// capture ctrl+c and stop CPU profiler
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
for sig := range c {
log.Printf("captured %v, stopping profiler and exiting..", sig)
pprof.StopCPUProfile()
os.Exit(1)
}
}()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-25 01:36:16
Wszystkie powyższe wydają się działać, gdy są połączone, ale strona sygnałów gobyexample ma naprawdę czysty i kompletny przykład przechwytywania sygnału. Warto dodać do tej listy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-20 13:01:31
Jest to kolejna wersja, która działa w przypadku, gdy masz jakieś zadania do oczyszczenia. Kod pozostawi proces czyszczenia w swojej metodzie.
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
)
func main() {
_,done1:=doSomething1()
_,done2:=doSomething2()
//do main thread
println("wait for finish")
<-done1
<-done2
fmt.Print("clean up done, can exit safely")
}
func doSomething1() (error, chan bool) {
//do something
done:=make(chan bool)
c := make(chan os.Signal, 2)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
<-c
//cleanup of something1
done<-true
}()
return nil,done
}
func doSomething2() (error, chan bool) {
//do something
done:=make(chan bool)
c := make(chan os.Signal, 2)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
<-c
//cleanup of something2
done<-true
}()
return nil,done
}
Jeśli chcesz wyczyścić główną funkcję, musisz przechwycić sygnał w głównym wątku za pomocą go func ().
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-20 00:52:29
Death jest prostą biblioteką, która używa kanałów i grupy oczekiwania do oczekiwania na sygnały zamknięcia. Po odebraniu sygnału wywoła metodę close na wszystkich Twoich strukturach, które chcesz wyczyścić.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-24 03:06:35
Możesz mieć inny goroutine, który wykrywa syscall.SIGINT i syscall.Sygnały SIGTERM i przekazują je do kanału za pomocą sygnału ./ Align = "left" / Możesz wysłać hook do tego goroutine za pomocą kanału i zapisać go w plasterku funkcji. Po wykryciu sygnału wyłączenia na kanale można wykonać te funkcje w plasterku. Może to być używane do czyszczenia zasobów, oczekiwania na uruchomienie goroutines, przechowywania danych lub drukowania częściowych sumie uruchomień.
Napisałem mały i proste narzędzie do dodawania i uruchamiania hooków przy zamykaniu. Mam nadzieję, że to może pomóc.
Https://github.com/ankit-arora/go-utils/blob/master/go-shutdown-hook/shutdown-hook.go
Możesz to zrobić w sposób "odroczony".Przykład wyłączenia serwera:
srv := &http.Server{}
go_shutdown_hook.ADD(func() {
log.Println("shutting down server")
srv.Shutdown(nil)
log.Println("shutting down server-done")
})
l, err := net.Listen("tcp", ":3090")
log.Println(srv.Serve(l))
go_shutdown_hook.Wait()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-09 18:45:31
Tak dla przypomnienia, jeśli ktoś potrzebuje sposobu na obsługę sygnałów w Windows. MiaĹ 'em Wymaganie obsĹ' ugi z prog a wywoĹ 'ania prog B Przez os/exec, ale prog B nigdy nie byĹ' w stanie zakoĹ "czyÄ ‡ z gracjÄ..., poniewaĹź wysyĹ 'anie sygnaĹ' Ăłw przez ex. cmd.Proces.Signal (syscall.SIGTERM) lub inne sygnały nie są obsługiwane w systemie Windows. Sposób, w jaki sobie radziłem, polega na utworzeniu pliku tymczasowego jako sygnału ex. .sygnał.term poprzez prog a i prog B musi sprawdzić, czy ten plik istnieje na bazie interwałów, jeśli plik istnieje, to WYJDŹ z programu i zajmij się czyszczeniem w razie potrzeby, jestem pewien, że są inne sposoby, ale to wykonało zadanie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-02 17:06:44