जावा में SIGKILL सिग्नल को कैसे इनायत करें


113

जब प्रोग्राम एक किल सिग्नल प्राप्त करता है तो आप कैसे सफाई करते हैं?

उदाहरण के लिए, एक ऐसा एप्लिकेशन है जिससे मैं कनेक्ट होता हूं, कोई भी थर्ड पार्टी ऐप (मेरा ऐप) चाहता है कि finishलॉग आउट करते समय एक कमांड भेजें । finishजब मेरे ऐप को पूरी तरह से नष्ट कर दिया गया हो तो उस कमांड को भेजने के लिए सबसे अच्छा क्या है kill -9?

संपादित करें 1: मार -9 पर कब्जा नहीं किया जा सकता है। मुझे सही करने के लिए धन्यवाद दोस्तों।

संपादित करें 2: मुझे लगता है कि यह मामला तब होगा जब कोई कॉल सिर्फ मार डालेगा जो कि ctrl-c के समान है


44
kill -9मेरे लिए इसका मतलब है: "बेगोन, बेईमानी प्रक्रिया, तुम्हारे साथ दूर!", जिस पर यह प्रक्रिया समाप्त हो जाएगी। तुरंत ही।
ZoogieZork

11
अधिकांश * निक्स पर जिन्हें मैं जानता हूं, मार -9 को किसी भी कार्यक्रम से नियंत्रित नहीं किया जा सकता है और इसे किसी भी कार्यक्रम से नियंत्रित किया जाता है चाहे वह किसी भी भाषा में लिखा गया हो।
राष्ट्रपति जेम्स के। पोल्क

2
@Begui: दूसरों ने जो टिप्पणी की है और उसका जवाब दिया है, अगर आपका Un x OS तुरंत नहीं मारता है * और प्रोग्राम को इस्तेमाल किए जाने वाले सभी परिणामों को मार डालो -9'ed , well ... OS टूट गया है।
SyntaxT3rr0r

1
किल -9 कमांड के बारे में, मैनपेज अधिक सटीक रूप से कहता है: "9 केआईएल (नॉन-कैटैलेबल, नॉन-इग्नोरबल किल)"। SIGKILL एक संकेत है जो OS द्वारा संभाला जाता है, एप्लिकेशन द्वारा नहीं।
user1338062

4
बस killCtrl-C के समान नहीं है, जैसा killकि निर्दिष्ट करने के लिए कि किस संकेत को SIGTERM भेजना है, जबकि Ctrl-C संकेत भेजता है।
एल्सगूजिक

जवाबों:


136

यह है असंभव एक SIGKILL को संभालने के लिए किसी भी भाषा में किसी भी कार्यक्रम के लिए,,। ऐसा इसलिए होता है कि किसी कार्यक्रम को समाप्त करना हमेशा संभव होता है, भले ही वह कार्यक्रम छोटा या दुर्भावनापूर्ण हो। लेकिन SIGKILL किसी प्रोग्राम को समाप्त करने का एकमात्र साधन नहीं है। दूसरे को SIGTERM का उपयोग करना है। प्रोग्राम उस सिग्नल को संभाल सकते हैं । कार्यक्रम को नियंत्रित, लेकिन तेजी से, बंद करके सिग्नल को संभालना चाहिए । जब कंप्यूटर बंद हो जाता है, तो शटडाउन प्रक्रिया का अंतिम चरण हर शेष प्रक्रिया को एक SIGTERM भेजता है, उन प्रक्रियाओं को कुछ सेकंड का अनुग्रह देता है, फिर उन्हें एक SIGKILL भेजता है।

शटडाउन हुक को पंजीकृत करने के अलावा किसी अन्य चीज के लिए इसे संभालने का तरीका । यदि आप ( SIGTERM ) का उपयोग कर सकते हैं तो शटडाउन हुक काम करेगा। ( SIGINT ) करता है शान से बाहर निकलने के लिए कार्यक्रम के कारण और बंद हुक चलाते हैं।kill -9kill -15kill -2

एक नया वर्चुअल-मशीन शटडाउन हुक पंजीकृत करता है।

दो प्रकार की घटनाओं के जवाब में जावा वर्चुअल मशीन बंद हो जाती है:

  • प्रोग्राम सामान्य रूप से बाहर निकलता है, जब अंतिम गैर-डेमन थ्रेड बाहर निकलता है या जब निकास (समकक्ष, System.exit) विधि लागू होती है, या
  • वर्चुअल मशीन उपयोगकर्ता के अवरोधन, जैसे कि टाइपिंग ^ C, या सिस्टम-वाइड इवेंट, जैसे उपयोगकर्ता लॉगऑफ़ या सिस्टम शटडाउन के जवाब में समाप्त हो जाती है।

मैं OSX 10.6.3 पर निम्नलिखित परीक्षण कार्यक्रम की कोशिश की और पर kill -9यह था नहीं की उम्मीद के रूप में बंद हुक चलाने के लिए,। एक पर kill -15यह करता है बंद हुक हर बार चलाते हैं।

public class TestShutdownHook
{
    public static void main(String[] args) throws InterruptedException
    {
        Runtime.getRuntime().addShutdownHook(new Thread()
        {
            @Override
            public void run()
            {
                System.out.println("Shutdown hook ran!");
            }
        });

        while (true)
        {
            Thread.sleep(1000);
        }
    }
}

किसी kill -9भी कार्यक्रम में वास्तव में इनायत को संभालने का कोई तरीका नहीं है ।

दुर्लभ परिस्थितियों में वर्चुअल मशीन गर्भपात कर सकती है, यानी सफाई बंद किए बिना दौड़ना बंद कर दें। यह तब होता है जब वर्चुअल मशीन बाहरी रूप से समाप्त हो जाती है, उदाहरण के लिए यूनिक्स पर SIGKILL सिग्नल या Microsoft Windows पर टर्मिनेटप्रोसेस कॉल।

एक को संभालने के लिए एकमात्र वास्तविक विकल्प kill -9दूर जाने के लिए या एक आवरण स्क्रिप्ट का उपयोग करने के लिए अपने मुख्य कार्यक्रम के लिए एक और वॉकर कार्यक्रम घड़ी है। आप इसे शेल स्क्रिप्ट के साथ कर सकते हैं ps, जो सूची में आपके प्रोग्राम की तलाश कर रही कमांड को प्रदूषित करती है और गायब होने पर तदनुसार कार्य करती है।

#!/usr/bin/env bash

java TestShutdownHook
wait
# notify your other app that you quit
echo "TestShutdownHook quit"

12

वहाँ रहे हैं देखते हैं - कुछ JVMs में अपने स्वयं के संकेतों को संभालने के लिए तरीके हॉटस्पॉट JVM के बारे में इस लेख उदाहरण के लिए।

सन इंटरनल sun.misc.Signal.handle(Signal, SignalHandler)मेथड कॉल का उपयोग करके आप सिग्नल हैंडलर को पंजीकृत करने में भी सक्षम हैं, लेकिन संभवतः जेवीएम द्वारा उपयोग किए जाने वाले INTया जैसे सिग्नल के लिए नहीं TERM

किसी भी सिग्नल को संभालने में सक्षम होने के लिए आपको जेवीएम और ऑपरेटिंग सिस्टम क्षेत्र से बाहर कूदना होगा।

मैं आमतौर पर (उदाहरण के लिए) असामान्य समाप्ति का पता लगाने के लिए एक पर्ल स्क्रिप्ट के अंदर अपने जेवीएम को लॉन्च करना चाहता हूं, लेकिन waitpidसिस्टम कॉल का उपयोग करके स्क्रिप्ट को जेवीएम के लिए इंतजार करना पड़ता है ।

मुझे तब सूचित किया जाता है जब भी जेवीएम बाहर निकलता है, और यह क्यों बाहर निकलता है, और आवश्यक कार्रवाई कर सकता है।


3
ध्यान दें कि आप कैप्चर कर सकते हैं INTऔर TERMसाथ में sun.misc.Signal, लेकिन आप संभाल नहीं सकते QUITक्योंकि JVM इसे डीबगिंग के लिए सुरक्षित रखता है, और न ही KILLक्योंकि OS JVM को तुरंत समाप्त कर देगा। या तो संभालने का प्रयास करेंगे IllegalArgumentException
डिमो 414 14

12

मैं उम्मीद होती है कि JVM शान से बीच में आता है ( thread.interrupt()) चल रहे सभी आवेदन द्वारा बनाई धागे, कम से कम संकेतों के लिए SIGINT (kill -2)और SIGTERM (kill -15)

इस तरह, सिग्नल को उनके पास भेजा जाएगा, जो मानक तरीके से एक सुंदर रूप से थ्रेड रद्द करने और संसाधन को अंतिम रूप देने की अनुमति देगा ।

लेकिन यह मामला नहीं है (कम से कम मेरे जेवीएम कार्यान्वयन में:) Java(TM) SE Runtime Environment (build 1.8.0_25-b17), Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

जैसा कि अन्य उपयोगकर्ताओं ने टिप्पणी की है, शटडाउन हुक का उपयोग अनिवार्य लगता है।

तो, मैं इसे कैसे संभालूंगा?

खैर पहले, मुझे सभी कार्यक्रमों में इसकी परवाह नहीं है, केवल उन लोगों में जहां मैं उपयोगकर्ता रद्द करने और अनपेक्षित छोरों पर नज़र रखना चाहता हूं। उदाहरण के लिए, कल्पना करें कि आपका जावा प्रोग्राम अन्य द्वारा प्रबंधित एक प्रक्रिया है। आप अंतर करना चाहते हैं कि क्या इसे इनायत से ( SIGTERMप्रबंधक प्रक्रिया से) समाप्त किया गया है या एक शटडाउन हुआ है (स्वचालित रूप से स्टार्टअप पर काम को फिर से शुरू करने के लिए)।

एक आधार के रूप में, मैं हमेशा अपने लंबे समय तक चलने वाले थ्रेड्स को समय-समय पर बाधित स्थिति से अवगत कराता हूं और InterruptedExceptionअगर वे बाधित होते हैं तो फेंक देते हैं । यह डेवलपर द्वारा नियंत्रित तरीके से निष्पादन को अंतिम रूप देने में सक्षम बनाता है (मानक अवरोधक संचालन के समान परिणाम भी)। फिर, थ्रेड स्टैक के शीर्ष स्तर पर, InterruptedExceptionकैप्चर किया जाता है और उपयुक्त क्लीन-अप किया जाता है। इन थ्रेड्स को एक रुकावट अनुरोध का जवाब देने के लिए जाना जाता है। उच्च सामंजस्य डिजाइन।

इसलिए, इन मामलों में, मैं एक शटडाउन हुक जोड़ता हूं, जो मुझे लगता है कि जेवीएम को डिफ़ॉल्ट रूप से करना चाहिए: मेरे एप्लिकेशन द्वारा बनाए गए सभी गैर-डेमॉन थ्रेड्स को बाधित करें जो अभी भी चल रहे हैं:

Runtime.getRuntime().addShutdownHook(new Thread() {
    @Override
    public void run() {
        System.out.println("Interrupting threads");
        Set<Thread> runningThreads = Thread.getAllStackTraces().keySet();
        for (Thread th : runningThreads) {
            if (th != Thread.currentThread() 
                && !th.isDaemon() 
                && th.getClass().getName().startsWith("org.brutusin")) {
                System.out.println("Interrupting '" + th.getClass() + "' termination");
                th.interrupt();
            }
        }
        for (Thread th : runningThreads) {
            try {
                if (th != Thread.currentThread() 
                && !th.isDaemon() 
                && th.isInterrupted()) {
                    System.out.println("Waiting '" + th.getName() + "' termination");
                    th.join();
                }
            } catch (InterruptedException ex) {
                System.out.println("Shutdown interrupted");
            }
        }
        System.out.println("Shutdown finished");
    }
});

Github पर पूरा परीक्षण आवेदन: https://github.com/idelvall/kill-test


6

आप उपयोग कर सकते हैं Runtime.getRuntime().addShutdownHook(...), लेकिन आपको इस बात की गारंटी नहीं दी जा सकती है कि यह किसी भी स्थिति में कहा जाएगा ।


12
लेकिन मार -9 के मामले में यह लगभग निश्चित रूप से नहीं चलेगा।
राष्ट्रपति जेम्स के। पोल्क

1

किल -9 पर प्रतिक्रिया करने का एक तरीका है: यह एक अलग प्रक्रिया है जो कि मारे जाने की प्रक्रिया की निगरानी करती है और यदि आवश्यक हो तो साफ करती है। इसमें संभवतः IPC शामिल होगा और यह काफी काम का होगा, और आप अभी भी एक ही समय में दोनों प्रक्रियाओं को मारकर इसे ओवरराइड कर सकते हैं। मुझे लगता है कि यह ज्यादातर मामलों में परेशानी के लायक नहीं होगा।

जो भी -9 के साथ एक प्रक्रिया को मारता है, उसे सैद्धांतिक रूप से पता होना चाहिए कि वह क्या कर रहा है / और यह असंगत स्थिति में चीजों को छोड़ सकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.