मैं कब्जा करना चाहता हूं Ctrl+CSIGINT
कंसोल से भेजे ( ) सिग्नल और कुछ आंशिक रन योग प्रिंट करता ।
क्या गोलंग में यह संभव है?
नोट: जब मैंने पहली बार प्रश्न पोस्ट किया था तो मैं इसके बजाय भ्रमित Ctrl+Cहोने के बारे में था ।SIGTERM
SIGINT
मैं कब्जा करना चाहता हूं Ctrl+CSIGINT
कंसोल से भेजे ( ) सिग्नल और कुछ आंशिक रन योग प्रिंट करता ।
क्या गोलंग में यह संभव है?
नोट: जब मैंने पहली बार प्रश्न पोस्ट किया था तो मैं इसके बजाय भ्रमित Ctrl+Cहोने के बारे में था ।SIGTERM
SIGINT
जवाबों:
आप आने वाले संकेतों को संभालने के लिए ओएस / सिग्नल पैकेज का उपयोग कर सकते हैं । Ctrl+ Cहै SIGINT ताकि आप जाल करने के लिए इसका उपयोग कर सकते 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
}
}()
जिस तरह से आप अपने कार्यक्रम को समाप्त करने और जानकारी प्रिंट करने के लिए कहते हैं, वह पूरी तरह से आपके ऊपर है।
for sig := range g {
, आप <-sigchan
इस पिछले उत्तर में भी उपयोग कर सकते हैं : stackoverflow.com/questions/8403862/…
go run
कंसोल में चलाते हैं और ^ C के माध्यम से एक SIGTERM भेजते हैं, तो सिग्नल चैनल में लिखा जाता है और प्रोग्राम प्रतिक्रिया देता है, लेकिन अप्रत्याशित रूप से लूप से बाहर निकलता है। इसका कारण यह है कि SIGRERM भी जाता है go run
! (इससे मुझे काफी भ्रम हो गया!)
runtime.Gosched
एक उपयुक्त स्थान पर कॉल करना चाहिए (आपके कार्यक्रम के मुख्य लूप में, यदि यह एक है)
यह काम:
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
}
}
अन्य उत्तरों में थोड़ा जोड़ने के लिए, यदि आप वास्तव में SIGTERM (किल कमांड द्वारा भेजा गया डिफ़ॉल्ट संकेत) को पकड़ना चाहते हैं, तो आप उपयोग कर सकते हैं syscall.SIGTERM
os.Interrupt के स्थान पर । खबरदार कि syscall इंटरफ़ेस सिस्टम-विशिष्ट है और हर जगह काम नहीं कर सकता है (उदाहरण के लिए विंडोज़)। लेकिन यह अच्छी तरह से दोनों को पकड़ने के लिए काम करता है:
c := make(chan os.Signal, 2)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
....
signal.Notify
समारोह एक बार में कई संकेतों को निर्दिष्ट करने की अनुमति देता है। इस प्रकार, आप अपने कोड को सरल बना सकते हैं signal.Notify(c, os.Interrupt, syscall.SIGTERM)
।
os.Kill
से मेल खाती है syscall.Kill
, जो एक संकेत है जिसे भेजा जा सकता है लेकिन पकड़ा नहीं जाता। इसके कमांड के बराबर kill -9 <pid>
। यदि आप kill <pid>
आकर्षक रूप से शटडाउन पकड़ना चाहते हैं , तो आपको इसका उपयोग करना होगा syscall.SIGTERM
।
ऊपर दिए गए उत्तर में एक (दो पोस्टिंग के समय) एक या दो छोटे टाइपो थे, इसलिए यहाँ साफ किया गया संस्करण है। इस उदाहरण में मैं 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)
}
}()
runtime.Gosched
एक उपयुक्त स्थान पर कॉल करना चाहिए (आपके प्रोग्राम के मुख्य लूप में, यदि यह एक है)
उपरोक्त सभी काम करते हैं जब spliced में दिखाई देते हैं, लेकिन gobyexample के सिग्नल पृष्ठ में सिग्नल कैप्चरिंग का वास्तव में स्वच्छ और पूर्ण उदाहरण है। इस सूची में जोड़ने के लायक।
मृत्यु एक साधारण पुस्तकालय है जो शटडाउन संकेतों के लिए प्रतीक्षा करने के लिए चैनलों और एक प्रतीक्षा समूह का उपयोग करता है। एक बार जब संकेत प्राप्त हो जाता है तो यह आपके सभी संरूपों पर एक करीबी विधि कहेगा जिसे आप साफ करना चाहते हैं।
आपके पास एक अलग गोरोइन हो सकता है जो syscall.SIGINT और syscall.SIGTERM संकेतों का पता लगाता है और सिग्नल का उपयोग करके उन्हें एक चैनल में रिले करता है । नोटिफाइ करें । आप एक चैनल का उपयोग करके उस गोरोइन को एक हुक भेज सकते हैं और इसे फ़ंक्शन स्लाइस में सहेज सकते हैं। जब चैनल पर शटडाउन सिग्नल का पता चलता है, तो आप स्लाइस में उन फ़ंक्शन को निष्पादित कर सकते हैं। इसका उपयोग संसाधनों को साफ करने के लिए किया जा सकता है, गोरोइन को चलाने के लिए प्रतीक्षा करें, डेटा को बनाए रखने या आंशिक रन योग को प्रिंट करने के लिए।
मैंने शटडाउन पर हुक जोड़ने और चलाने के लिए एक छोटी और सरल उपयोगिता लिखी। आशा है कि यह मदद की हो सकती है।
https://github.com/ankit-arora/go-utils/blob/master/go-shutdown-hook/shutdown-hook.go
आप इसे 'डेफर' अंदाज में कर सकते हैं।
एक सर्वर को इनायत से बंद करने के लिए उदाहरण:
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()
यह एक और संस्करण है जो उस स्थिति में काम करता है जब आपके पास सफाई के लिए कुछ कार्य हैं। कोड उनकी विधि में सफाई प्रक्रिया को छोड़ देगा।
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
}
यदि आपको मुख्य फ़ंक्शन को साफ करने की आवश्यकता है, तो आपको मुख्य फ़ेंक () के साथ-साथ मुख्य थ्रेड का उपयोग करके सिग्नल पर कब्जा करने की आवश्यकता है।
बस रिकॉर्ड के लिए अगर किसी को विंडोज पर सिग्नल को संभालने का तरीका चाहिए। मुझे ओएस / एग्जीक्यूटिव के माध्यम से कॉलिंग प्रोग बी से निपटने की आवश्यकता थी लेकिन प्रोग बी कभी भी सुंदर तरीके से समाप्त करने में सक्षम नहीं था क्योंकि पूर्व के माध्यम से संकेत भेज रहा था। cmd.Process.Signal (syscall.SIGTERM) या अन्य सिग्नल विंडोज पर समर्थित नहीं हैं। जिस तरह से मैंने संभाला है वह एक सिग्नल पूर्व के रूप में एक अस्थायी फ़ाइल बना रहा है। प्रोग ए। और प्रोग बी के माध्यम से .signal.term की जाँच करने की आवश्यकता है कि क्या फ़ाइल अंतराल आधार पर मौजूद है, यदि फ़ाइल मौजूद है तो यह प्रोग्राम से बाहर निकल जाएगी और यदि आवश्यक हो तो सफाई को संभाल लेगी, मुझे यकीन है कि अन्य तरीके भी हैं लेकिन यह काम किया है।