मैं यूनिक्स में एक अनियंत्रित स्क्रिप्ट को कैसे निर्धारित करूं?


93

मैं एक डेमोनाइज़र चाहूंगा जो एक अनियंत्रित, सामान्य स्क्रिप्ट या कमांड को डेमॉन में बदल सकता है ।

दो सामान्य मामले हैं जिनसे मैं निपटना चाहूंगा:

  1. मेरे पास एक स्क्रिप्ट है जो हमेशा के लिए चलनी चाहिए। यदि यह कभी भी (या रिबूट पर) मर जाता है, तो इसे पुनरारंभ करें। ऐसा न हो कि एक साथ दो प्रतियाँ चल रही हों (पता लगाएँ कि क्या कोई प्रति पहले से चल रही है और उस स्थिति में उसे लॉन्च न करें)।

  2. मेरे पास एक सरल स्क्रिप्ट या कमांड लाइन कमांड है जिसे मैं हमेशा के लिए बार-बार निष्पादित करना चाहता हूं (रन के बीच एक छोटा विराम के साथ)। दोबारा, स्क्रिप्ट की दो प्रतियों को कभी भी एक साथ चलाने की अनुमति न दें।

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

ध्यान दें कि मौजूदा स्क्रिप्ट में फ़ाइल-लॉकिंग कोड या पीआईडी ​​रिकॉर्डिंग को शामिल करते हुए समाधान को शामिल नहीं करना चाहिए।

अधिक विशेष रूप से, मैं एक कार्यक्रम "डेमनीज़" चाहूंगा जिसे मैं पसंद कर सकता हूं

% daemonize myscript arg1 arg2

या, उदाहरण के लिए,

% daemonize 'echo `date` >> /tmp/times.txt'

जो दिनांक की बढ़ती सूची को बनाए रखेगा। (ध्यान दें कि यदि तर्क करने के लिए तर्क एक स्क्रिप्ट है जो हमेशा के मामले में 1 से ऊपर के रूप में चलता है, तो फिर भी सही काम करना होगा, आवश्यक होने पर इसे फिर से शुरू करना।) फिर मैं अपने .login में ऊपर की तरह एक कमांड डाल सकता हूं। और / या क्रोन इसे प्रति घंटा या सूक्ष्म रूप से (इस बात पर निर्भर करता है कि मैं इसके बारे में चिंतित कैसे अप्रत्याशित रूप से मर रहा था)।

NB: डेमनीज स्क्रिप्ट को कमांड स्ट्रिंग को याद रखने की आवश्यकता होगी, यह डेमॉनेटाइजिंग है ताकि यदि उसी कमांड स्ट्रिंग को फिर से डेमनीफाई किया जाए तो यह दूसरी कॉपी लॉन्च नहीं करता है।

इसके अलावा, समाधान को आदर्श रूप से ओएस एक्स और लिनक्स दोनों पर काम करना चाहिए लेकिन एक या दूसरे के लिए समाधान का स्वागत है।

संपादित करें: यह ठीक है अगर आपको इसे लागू करना है sudo daemonize myscript myargs

(अगर मैं यह सब गलत सोच रहा हूं या त्वरित और गंदे आंशिक समाधान हैं, तो मुझे भी यह सुनना अच्छा लगेगा।)


पुनश्च: मामले में यह उपयोगी है, यहाँ अजगर के लिए एक समान प्रश्न है।

और यह एक ऐसी ही सवाल का जवाब क्या एक मनमाना स्क्रिप्ट की एक त्वरित और गंदा चित्रण इस के लिए एक उपयोगी मुहावरा हो गया लगता है है:


1
एक शुद्ध खोल संस्करण के लिए serverfault.com/questions/311593/… देखें
w00t

जवाबों:


90

आप यूनिक्स में किसी भी निष्पादन योग्य को नोहाप और ऑपरेटर के उपयोग से निर्धारित कर सकते हैं:

nohup yourScript.sh script args&

Nohup कमांड आपको अपनी स्क्रिप्ट को मारे बिना अपना शेल सत्र बंद करने की अनुमति देता है, जबकि & आपकी स्क्रिप्ट को पृष्ठभूमि में रखता है ताकि आपको अपना सत्र जारी रखने के लिए एक शेल प्रॉम्प्ट मिल सके। इसके साथ एकमात्र मामूली समस्या है मानक आउट और मानक त्रुटि दोनों को .nohup.out पर भेज दिया जाता है, इसलिए यदि आप इस मनोर में कई स्क्रिप्ट शुरू करते हैं, तो उनका आउटपुट इंटरवेट किया जाएगा। एक बेहतर आदेश होगा:

nohup yourScript.sh script args >script.out 2>script.error&

यह आपकी पसंद की फ़ाइल के लिए मानक मानक और आपकी पसंद की एक अलग फ़ाइल में मानक त्रुटि भेजेगा। यदि आप मानक फ़ाइल और मानक त्रुटि दोनों के लिए सिर्फ एक फ़ाइल का उपयोग करना चाहते हैं, तो आप यह कर सकते हैं:

nohup yourScript.sh script args >script.out 2>&1 &

2> & 1 शेल को मानक फ़ाइल (फ़ाइल डिस्क्रिप्टर 1) के रूप में उसी फ़ाइल पर रीडायरेक्ट मानक त्रुटि (फ़ाइल डिस्क्रिप्टर 2) को बताता है।

केवल एक बार एक कमांड चलाने के लिए और इसे फिर से शुरू करें यदि यह मर जाता है तो आप इस स्क्रिप्ट का उपयोग कर सकते हैं:

#!/bin/bash

if [[ $# < 1 ]]; then
    echo "Name of pid file not given."
    exit
fi

# Get the pid file's name.
PIDFILE=$1
shift

if [[ $# < 1 ]]; then
    echo "No command given."
    exit
fi

echo "Checking pid in file $PIDFILE."

#Check to see if process running.
PID=$(cat $PIDFILE 2>/dev/null)
if [[ $? = 0 ]]; then
    ps -p $PID >/dev/null 2>&1
    if [[ $? = 0 ]]; then
        echo "Command $1 already running."
        exit
    fi
fi

# Write our pid to file.
echo $$ >$PIDFILE

# Get command.
COMMAND=$1
shift

# Run command until we're killed.
while true; do
    $COMMAND "$@"
    sleep 10 # if command dies immediately, don't go into un-ctrl-c-able loop
done

पहला तर्क उपयोग करने के लिए pid फ़ाइल का नाम है। दूसरा तर्क आज्ञा है। और अन्य सभी तर्क कमांड के तर्क हैं।

यदि आप इस स्क्रिप्ट को पुनः नाम देते हैं। तो यह है कि आप इसे कैसे कहेंगे:

nohup restart.sh pidFileName yourScript.sh script args >script.out 2>&1 &

बहुत बढ़िया; धन्यवाद। मुझे आश्चर्य है कि इसे फिर से शुरू करने में देरी के लिए एक विकल्प भी होना चाहिए। या शायद इस के साथ संयोजन के रूप में उपयोग करने के लिए बेहतर है: stackoverflow.com/questions/555116/…
dreeves

4
यह केवल SIGHUP को संभालता है, अन्य (सामान्य रूप से) घातक संकेत हैं जिन्हें संभाला जाना चाहिए।
टिम पोस्ट

इस लिपि को सुधारने का एक और तरीका शायद यह है कि $ PIDFILE को अपने स्थान पर रखने के लिए एक अच्छे स्थान के साथ आने के बजाय इसे एक arg के रूप में निर्दिष्ट करने की आवश्यकता होती है। यह खुद के बाद भी साफ नहीं करता है! (जो एक के साथ सीधा होना चाहिएtrap EXIT )
स्टीवन लू

इसके अलावा, विचार है कि के उपयोग <में testएक ASCII तुलना नहीं एक पूर्णांक तुलना है। यह अभी भी काम कर सकता है, लेकिन इसमें कीड़े हो सकते हैं।
स्टीवन लू

मैंने इस स्क्रिप्ट पर अपने फ़िक्सेस पोस्ट किए हैं
स्टीवन लू

33

मैं लंबे उत्तर के लिए माफी माँगता हूँ (कृपया मेरे उत्तरों की कल्पना कैसे करें इस बारे में टिप्पणी देखें)। मैं व्यापक होने की कोशिश कर रहा हूं, इसलिए आपके पास जितना संभव हो उतना अच्छा है। :-)

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

इसमें डेमोनटूल का उपयोग करना शामिल है । बाकि पोस्ट में यह बताया गया है कि कैसे डेमोनटूल का उपयोग करके सेवाओं को स्थापित किया जाए।

प्रारंभिक व्यवस्था

  1. कैसे डेमोंटोल्स को स्थापित करने के निर्देशों का पालन करें । कुछ वितरण (जैसे, डेबियन, उबंटू) में पहले से ही इसके लिए पैकेज हैं, इसलिए बस उसी का उपयोग करें।
  2. एक निर्देशिका बनाओ /service। इंस्टॉलर को पहले से ही ऐसा करना चाहिए था, लेकिन बस सत्यापित करें, या यदि मैन्युअल रूप से इंस्टॉल करना है। यदि आप इस स्थान को नापसंद करते हैं, तो आप इसे अपनी svscanbootस्क्रिप्ट में बदल सकते हैं , हालांकि अधिकांश daemontools उपयोगकर्ताओं का उपयोग करने के लिए उपयोग किए जाते हैं /serviceऔर यदि आप इसका उपयोग नहीं करते हैं तो भ्रमित हो जाएंगे।
  3. यदि आप उबंटू या किसी अन्य डिस्ट्रो का उपयोग कर रहे हैं जो मानक का उपयोग नहीं करता है init(अर्थात, उपयोग नहीं करता है /etc/inittab), तो आपको पूर्व-स्थापित का उपयोग करने की आवश्यकता होगीinittabsvscanboot कॉल करने की व्यवस्था करने के लिए आधार के रूप करना होगा init। यह मुश्किल नहीं है, लेकिन आपको यह जानना होगा initकि आपके ओएस का उपयोग कैसे करें । svscanbootएक स्क्रिप्ट है जो कॉल करती है svscan, जो सेवाओं की तलाश का मुख्य काम करती है; यह से कहा जाता है initतो initअगर यह किसी भी कारण से मर जाता है उसे पुन: प्रारंभ करने के लिए व्यवस्था करेंगे।

प्रति-सेवा सेटअप

  1. प्रत्येक सेवा को एक सेवा निर्देशिका की आवश्यकता होती है , जो सेवा के बारे में हाउसकीपिंग जानकारी संग्रहीत करती है। आप इन सेवा निर्देशिकाओं को रखने के लिए स्थान भी बना सकते हैं ताकि वे सभी एक ही स्थान पर हों; आमतौर पर मैं उपयोग करता हूं /var/lib/svscan, लेकिन कोई भी नया स्थान ठीक रहेगा।
  2. मैं आमतौर पर सेवा निर्देशिका को सेट करने के लिए स्क्रिप्ट का उपयोग करता हूं , बहुत सारे मैनुअल दोहराए गए कार्यों को बचाने के लिए। जैसे,

    sudo mkservice -d /var/lib/svscan/some-service-name -l -u user -L loguser "command line here"

    कहाँ पे some-service-nameवह नाम आप अपनी सेवा देना चाहते हैं, userउस सेवा loguserको चलाने के लिए उपयोगकर्ता है और लॉगर को चलाने के लिए उपयोगकर्ता है। (लॉगिंग बस थोड़ा सा समझाया गया है।)

  3. आपकी सेवा को अग्रभूमि में चलाना होगा । यदि आपका प्रोग्राम डिफॉल्ट रूप से बैकग्राउंड करता है, लेकिन उसे डिसेबल करने का विकल्प है, तो ऐसा करें। यदि आपके प्रोग्राम की पृष्ठभूमि इसे निष्क्रिय करने के तरीके के बिना है fghack, तो इस पर पढ़ें , हालांकि यह एक व्यापार-बंद पर आता है: आप अब प्रोग्राम का उपयोग करके नियंत्रित नहीं कर सकते svc
  4. runयह सुनिश्चित करने के लिए स्क्रिप्ट को संपादित करें कि आप यह क्या कर रहे हैं। sleepयदि आपको अपनी सेवा से अक्सर बाहर निकलने की उम्मीद है, तो आपको शीर्ष पर कॉल करने की आवश्यकता हो सकती है ।
  5. जब सब कुछ सही सेट हो जाता है, तो /serviceअपनी सेवा निर्देशिका को इंगित करने के लिए एक सिमलिंक बनाएं । (सीधे सेवा निर्देशिका को अंदर न रखें /service; इससे सेवा को हटाना कठिन हो जाता हैsvscan घड़ी ।)

लॉगिंग

  1. लॉगिंग का डेमोनटॉल्स तरीका सेवा को मानक उत्पादन (या मानक त्रुटि के लिए लॉग संदेश लिखना है, यदि आप स्क्रिप्ट के साथ उत्पन्न का उपयोग कर रहे हैं mkservice ) में ; svscanलॉगिंग सेवा में लॉग संदेश भेजने का ख्याल रखता है।
  2. लॉगिंग सेवा मानक इनपुट से लॉग संदेश लेती है। लॉगिंग सेवा स्क्रिप्ट द्वारा उत्पन्नmkservicelog/main निर्देशिका में स्वत: घुमाएगी, टाइमस्टैम्प्ड लॉग फ़ाइलों को बनाएगी । वर्तमान लॉग फ़ाइल को कहा जाता है current
  3. लॉगिंग सेवा को मुख्य सेवा से स्वतंत्र रूप से शुरू और बंद किया जा सकता है।
  4. लॉग फ़ाइलों के माध्यम से पाइपिंग tai64nlocalटाइमस्टैम्प का मानव-पठनीय प्रारूप में अनुवाद करेगी। (TAI64N एक 64-बिट परमाणु टाइमस्टैम्प है जिसमें नैनोसेकंड गिनती होती है।)

सेवाओं को नियंत्रित करना

  1. उपयोग svstatसेवा की स्थिति प्राप्त करने के लिए । ध्यान दें कि लॉगिंग सेवा स्वतंत्र है, और इसकी अपनी स्थिति है।
  2. आप अपनी सेवा (प्रारंभ, रोक, पुनः आरंभ, आदि) का उपयोग करके नियंत्रित करते हैं svc। उदाहरण के लिए, अपनी सेवा को पुनः आरंभ करने के लिए, उपयोग करें svc -t /service/some-service-name; -tका अर्थ है "भेजेंSIGTERM "।
  3. उपलब्ध अन्य संकेतों में शामिल हैं -h( SIGHUP), -a( SIGALRM), -1( SIGUSR1), -2( SIGUSR2), और -k(SIGKILL )।
  4. सेवा को नीचे करने के लिए, का उपयोग करें -d। आप downसेवा निर्देशिका में एक फ़ाइल बनाकर बूटअप पर स्वचालित रूप से शुरू होने से एक सेवा को रोक सकते हैं ।
  5. सेवा शुरू करने के लिए, का उपयोग करें -u । यह तब तक आवश्यक नहीं है जब तक कि आप इसे पहले से कम न कर दें (या इसे ऑटो-स्टार्ट न करें)।
  6. पर्यवेक्षक से बाहर निकलने, उपयोग करने के लिए कहने के लिए -x; आमतौर पर -dसेवा समाप्त करने के लिए भी इसका उपयोग किया जाता है । किसी सेवा को हटाने की अनुमति देने का यह सामान्य तरीका है, लेकिन आपको /serviceपहले से सेवा को अनलिंक करना svscanहोगा , अन्यथा पर्यवेक्षक को पुनरारंभ करना होगा। इसके अलावा, यदि आपने एक लॉगिंग सेवा ( mkservice -l) के साथ अपनी सेवा बनाई है, तो svc -dx /var/lib/svscan/some-service-name/logसेवा निर्देशिका को हटाने से पहले लॉगिंग पर्यवेक्षक (जैसे, ) से बाहर निकलना भी याद रखें ।

सारांश

पेशेवरों:

  1. daemontools सेवाओं को बनाने और प्रबंधित करने के लिए बुलेटप्रूफ तरीका प्रदान करता है। मैं इसे अपने सर्वर के लिए उपयोग करता हूं, और मैं इसकी अत्यधिक अनुशंसा करता हूं।
  2. इसकी लॉगिंग प्रणाली बहुत मजबूत है, जैसा कि सेवा ऑटो-पुनरारंभ सुविधा है।
  3. क्योंकि यह एक शेल स्क्रिप्ट के साथ सेवाएं शुरू करता है जिसे आप लिखते हैं / ट्यून करते हैं, लेकिन आप अपनी सेवा को पसंद कर सकते हैं।
  4. शक्तिशाली सेवा नियंत्रण उपकरण: आप किसी भी सेवा को सबसे अधिक संकेत भेज सकते हैं, और सेवाओं को मज़बूती से ऊपर और नीचे ला सकते हैं।
  5. आपकी सेवाओं को एक स्वच्छ निष्पादन वातावरण की गारंटी दी जाती है: वे उसी वातावरण, प्रक्रिया की सीमाओं, आदि के साथ निष्पादित करेंगे, जो initप्रदान करता है।

विपक्ष:

  1. प्रत्येक सेवा में थोड़ा सा सेटअप होता है। शुक्र है, यह केवल एक बार प्रति सेवा करने की जरूरत है।
  2. अग्रभूमि में चलाने के लिए सेवाएं स्थापित की जानी चाहिए। इसके अलावा, सर्वोत्तम परिणामों के लिए, उन्हें syslog या अन्य फ़ाइलों के बजाय मानक आउटपुट / मानक त्रुटि में प्रवेश करने के लिए सेट किया जाना चाहिए।
  3. अगर आप चीजों को करने के daemontools के लिए नए हैं, तो सीखने की अवस्था में तेजी लाएँ। आपको सेवाओं का उपयोग करके पुनः आरंभ करना होगा svc, और रन स्क्रिप्ट को सीधे नहीं चला सकते हैं (क्योंकि वे तब पर्यवेक्षक के नियंत्रण में नहीं होंगे)।
  4. हाउसकीपिंग फ़ाइलों के बहुत सारे, और हाउसकीपिंग प्रक्रियाओं के बहुत सारे। प्रत्येक सेवा को अपनी स्वयं की सेवा निर्देशिका की आवश्यकता होती है, और प्रत्येक सेवा एक पर्यवेक्षक प्रक्रिया का उपयोग उस सेवा को स्वत: पुनरारंभ करने के लिए करती है यदि वह मर जाती है। (आप कई सेवाओं है, तो आप देखेंगे बहुत सारे की superviseअपनी प्रक्रिया तालिका में प्रक्रियाओं।)

संतुलन में, मुझे लगता है कि डेमोनटूल आपकी आवश्यकताओं के लिए एक उत्कृष्ट प्रणाली है। मैं इसे सेट करने और इसे बनाए रखने के बारे में किसी भी प्रश्न का स्वागत करता हूं।


मेरा जवाब कैसे नाखूनों की कल्पना करता है: 1. आपको सेवाओं को स्थापित करना होगा, इसलिए जब तक आप डुप्लिकेट सेट नहीं करते हैं (और जब तक आपकी सेवा स्वयं पृष्ठभूमि नहीं करती), तब तक कोई डुप्लिकेट नहीं होगा। 2. supervise, पर्यवेक्षक, बाहर निकलने वाली किसी भी सेवा को फिर से शुरू करने का ख्याल रखता है। यह एक सेकंड का इंतजार करता है; यदि वह आपके लिए पर्याप्त समय नहीं है, तो सर्विस रन स्क्रिप्ट के शीर्ष पर एक नींद में रखें।
क्रिस जस्टर-यंग

2 ए। superviseस्वयं द्वारा समर्थित है svscan, इसलिए यदि कोई पर्यवेक्षक मर जाता है, तो इसे फिर से शुरू किया जाएगा। 2 बी। svscanद्वारा समर्थित है init, जो svscanआवश्यक के रूप में स्वतः पुनः आरंभ करेगा । 2c। यदि initकिसी कारण से आपकी मृत्यु हो जाती है, तो आप वैसे भी खराब हो जाते हैं। :-P
क्रिस जस्टर-यंग

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

3
हमारे पास एसओ और सामान्य रूप से नेट में इस तरह के अधिक पद होने चाहिए। वांछित प्रभाव को प्राप्त करने के तरीके पर सिर्फ एक नुस्खा नहीं है, लेकिन एक है जो व्यंजनों को समझाने के लिए परेशानी उठाती है। मैं इसे एक से अधिक बार क्यों नहीं बढ़ा सकता? : |
स्काईट्रेडर

12

मुझे लगता है कि आप कोशिश करना चाह सकते हैं start-stop-daemon(8)/etc/init.dउदाहरण के लिए किसी भी लिनक्स डिस्ट्रो में स्क्रिप्ट देखें । यह कमांड लाइन इनवॉल्ड या पीआईडी ​​फ़ाइल द्वारा शुरू की गई प्रक्रियाओं को खोज सकता है, इसलिए यह आपकी स्क्रिप्ट के लिए एक वॉचडॉग को छोड़कर आपकी सभी आवश्यकताओं से मेल खाता है। लेकिन आप हमेशा एक और डेमॉन वॉचडॉग स्क्रिप्ट शुरू कर सकते हैं जो आवश्यक होने पर बस अपनी स्क्रिप्ट को पुनरारंभ करता है।


फेडोरा में कोई स्टार्ट-स्टॉप-डेमॉन नहीं है, फिर भी, इसलिए इसके आधार पर स्क्रिप्ट पोर्टेबल नहीं हैं। देखें: fedoraproject.org/wiki/Features/start-stop-daemon
Bengt

OSX उपयोगकर्ताओं के लिए बस एक हेड-अप: कोई start-stop-daemonभी, या तो (10.9 के रूप में)।
mklement0

@ mklement0 अच्छा ... लगभग 5 वर्षों में बहुत कुछ बदल गया है।
एलेक्स बी

मेरा, समय कैसे उड़ता है। start-stop-daemonअभी भी जिंदा है और लिनक्स पर लात मार रहा है, हालांकि; लेकिन उत्तर stackoverflow.com/a/525406/45375 पढ़ने के बाद मुझे महसूस हुआ कि OSX अपनी बात करता है launchd:।
mklement0

12

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

यदि आपको अपने आवेदन को डेमॉन के रूप में स्वचालित रूप से शुरू करने की आवश्यकता है, तो आपको उपयुक्त इनिट-स्क्रिप्ट बनाने की आवश्यकता है।

आप निम्नलिखित टेम्पलेट का उपयोग कर सकते हैं:

#!/bin/sh
#
# mydaemon     This shell script takes care of starting and stopping
#               the <mydaemon>
#

# Source function library
. /etc/rc.d/init.d/functions


# Do preliminary checks here, if any
#### START of preliminary checks #########


##### END of preliminary checks #######


# Handle manual control parameters like start, stop, status, restart, etc.

case "$1" in
  start)
    # Start daemons.

    echo -n $"Starting <mydaemon> daemon: "
    echo
    daemon <mydaemon>
    echo
    ;;

  stop)
    # Stop daemons.
    echo -n $"Shutting down <mydaemon>: "
    killproc <mydaemon>
    echo

    # Do clean-up works here like removing pid files from /var/run, etc.
    ;;
  status)
    status <mydaemon>

    ;;
  restart)
    $0 stop
    $0 start
    ;;

  *)
    echo $"Usage: $0 {start|stop|status|restart}"
    exit 1
esac

exit 0

1
सही उत्तर के लिए एक उम्मीदवार की तरह दिखता है। विशेष रूप से इसकी "एकल उदाहरण जाँच" पर विचार करना।
मार्टिन विकमैन

यह सबसे अच्छा संभव उत्तर हो सकता है - मुझे यकीन नहीं है - लेकिन अगर आपको लगता है कि यह है, तो क्या आप इस बात के लिए स्पष्टीकरण भी शामिल कर सकते हैं कि मैंने प्रश्न में दिया गया चश्मा गलत क्यों है?
dreeves

मुझे killprocरोक भाग में पसंद नहीं है : यदि आपके पास एक प्रक्रिया थी, जो कहती है, भागा है java, तो killprocअन्य सभी जावा प्रक्रियाओं को भी मार दिया जाएगा।
क्रिस जस्टर-यंग

1
/Etc/rc.d/init.d/functions से, डेमनीज बाइनरी को एक नए शेल से शुरू करता है: $ cgroup $ nice / bin / bash -c $corelimit >/dev/null 2>&1 ; $*इसलिए मुझे संदेह है कि यह किसी भी चीज़ का डोनेमाइज़ करने जा रहा है ...
mbonnin

1
मुझे पता है कि यह पुराना है, लेकिन बाद में इसे खोजने वाले किसी के लिए ... यह सही है। /etc/init.d/functions में परिभाषित "डेमॉन" वास्तव में आपके लिए नहीं है । यह cgroups करने के लिए सिर्फ एक आवरण है, जांचें कि क्या प्रक्रिया पहले से ही चल रही है, एक उपयोगकर्ता सेट करें, अच्छा और अलिमित मान सेट करें, आदि यह आपके लिए प्रक्रिया को निर्धारित नहीं करता है । यह अभी भी आपका अपना काम है। :)
जाकेम

7

पहले से ही उल्लेख के विकल्प के रूप में , daemonizeऔर libslack पैकेज का डेमॉन कमांड है।daemontools

daemon काफी विन्यास योग्य है और सभी थकाऊ डेमन सामान जैसे कि स्वचालित पुनरारंभ, लॉगिंग या पिडफाइल हैंडलिंग के बारे में परवाह करता है।


5

यदि आप विशेष रूप से ओएस एक्स का उपयोग कर रहे हैं, तो मेरा सुझाव है कि आप लॉन्च पर काम करते हैं। यह सुनिश्चित करने के लिए स्वचालित रूप से जांच करेगा कि आपकी स्क्रिप्ट चल रही है और यदि आवश्यक हो तो उसे फिर से लॉन्च करें। इसमें सभी प्रकार के शेड्यूलिंग फीचर्स भी शामिल हैं। इसमें आवश्यकता 1 और 2 दोनों को संतुष्ट करना चाहिए।

यह सुनिश्चित करने के लिए कि आपकी स्क्रिप्ट की केवल एक प्रति ही चल सकती है, आपको PID फ़ाइल का उपयोग करने की आवश्यकता है। आम तौर पर मैं /var/run/.pid पर एक फ़ाइल लिखता हूं जिसमें वर्तमान चल रहे उदाहरण का PID होता है। यदि प्रोग्राम मौजूद होने पर फ़ाइल मौजूद है, तो यह जाँचता है कि क्या फ़ाइल में PID वास्तव में चल रहा है (प्रोग्राम क्रैश हो गया है या अन्यथा PID फ़ाइल को हटाना भूल सकता है)। यदि यह है, तो गर्भपात करें। यदि नहीं, तो चलना शुरू करें और पीआईडी ​​फ़ाइल को अधिलेखित करें।


5

Daemontools ( http://cr.yp.to/daemontools.html ) यह करने के लिए उपयोग किए जाने वाले सुंदर हार्ड-कोर उपयोगिताओं का एक सेट है, जो dj bernstein द्वारा लिखा गया है। मैंने कुछ सफलता के साथ इसका उपयोग किया है। इसके बारे में कष्टप्रद हिस्सा यह है कि जब आप उन्हें चलाते हैं तो कोई भी स्क्रिप्ट कोई भी दृश्यमान परिणाम नहीं लौटाती है - बस अदृश्य रिटर्न कोड। लेकिन एक बार यह बुलेटप्रूफ चल रहा है।


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

3

सबसे पहले http://code.activestate.com/recipes/278731/createDaemon() से प्राप्त करें

फिर मुख्य कोड:

import subprocess
import sys
import time

createDaemon()

while True:
    subprocess.call(" ".join(sys.argv[1:]),shell=True)
    time.sleep(10)

ऊह, धन्यवाद! इसे थोड़ा और सामान्य बनाना चाहते हैं ताकि आप "डेमूनाइज फू आरजी 1 आरजी 2" के साथ-साथ "डेमनीज 'फू आरजी 1 आरजी 2' कर सकें?"
dreeves

ठीक है, यह अब तर्कों में शामिल हो जाएगा - हालाँकि आपको इसे बदलना होगा यदि आप कभी भी अपने तर्कों के अंदर रिक्त स्थान चाहते हैं।
डगलस लीडर

धन्यवाद डगलस! हालांकि एक बड़ा दोष है: "डूमेनाइज फू" चलाने से दो बार चलने वाली फू की दो प्रतियां शुरू होती हैं।
dreeves

आप कुछ PID रिकॉर्डिंग कोड जोड़ सकते हैं, लेकिन यह केवल एक बार स्क्रिप्ट चलाने के लिए सबसे अच्छा हो सकता है ...
डगलस लीडर

मैं उस तरह की सोच के रूप में पूरे "daemonize" आवरण अवधारणा के लिए मौलिक है। (उदाहरण के लिए, मैं यह सुनिश्चित करने के लिए प्रति घंटा या सूक्ष्मता से क्रोन कर सकता हूं कि यह हमेशा चल रहा था।) क्या मैं इस गलत सोच रहा हूं? क्या CreateDaemon पहले से ही किसी तरह की गारंटी देता है? रिबूट के बाद क्या?
1

1

यह एक उदाहरण के साथ पूरा होने वाला एक कार्यशील संस्करण है जिसे आप एक खाली निर्देशिका में कॉपी कर सकते हैं और आज़मा सकते हैं (CPAN निर्भरताएँ स्थापित करने के बाद, जो Getopt :: Long , File :: Spec , File :: Pid , और IPC :: System: : सरल - सभी सुंदर मानक और किसी भी हैकर के लिए अत्यधिक अनुशंसित हैं: आप उन सभी को एक साथ स्थापित कर सकते हैं cpan <modulename> <modulename> ...)।


keepAlive.pl:

#!/usr/bin/perl

# Usage:
# 1. put this in your crontab, to run every minute:
#     keepAlive.pl --pidfile=<pidfile> --command=<executable> <arguments>
# 2. put this code somewhere near the beginning of your script,
#    where $pidfile is the same value as used in the cron job above:
#     use File::Pid;
#     File::Pid->new({file => $pidfile})->write;

# if you want to stop your program from restarting, you must first disable the
# cron job, then manually stop your script. There is no need to clean up the
# pidfile; it will be cleaned up automatically when you next call
# keepAlive.pl.

use strict;
use warnings;

use Getopt::Long;
use File::Spec;
use File::Pid;
use IPC::System::Simple qw(system);

my ($pid_file, $command);
GetOptions("pidfile=s"   => \$pid_file,
           "command=s"   => \$command)
    or print "Usage: $0 --pidfile=<pidfile> --command=<executable> <arguments>\n", exit;

my @arguments = @ARGV;

# check if process is still running
my $pid_obj = File::Pid->new({file => $pid_file});

if ($pid_obj->running())
{
    # process is still running; nothing to do!
    exit 0;
}

# no? restart it
print "Pid " . $pid_obj->pid . " no longer running; restarting $command @arguments\n";

system($command, @arguments);

example.pl:

#!/usr/bin/perl

use strict;
use warnings;

use File::Pid;
File::Pid->new({file => "pidfile"})->write;

print "$0 got arguments: @ARGV\n";

अब आप ऊपर दिए गए उदाहरण को लागू कर सकते हैं: ./keepAlive.pl --pidfile=pidfile --command=./example.pl 1 2 3और फ़ाइल pidfileबनाई जाएगी, और आप आउटपुट देखेंगे:

Pid <random number here> no longer running; restarting ./example.pl 1 2 3
./example.pl got arguments: 1 2 3

मेरा मानना ​​है कि यह अनुमान लगाने के लिए काफी नहीं है, अगर मैं सही ढंग से समझता हूं। आपके समाधान में (धन्यवाद, btw!) जिस कार्यक्रम को आप करना चाहते हैं उसे अपने PID को PID फ़ाइल में लिखने के लिए संशोधित करना होगा। मैं एक उपयोगिता के लिए उम्मीद कर रहा हूं जो एक मनमाना स्क्रिप्ट को निष्क्रिय कर सकती है।
१।

@ ड्रीम्स: हाँ, लेकिन इसके आसपास दो तरीके हैं: 1. KeepAlive.pl (जैसे example.pl) द्वारा लिखी गई स्क्रिप्ट बस वास्तविक प्रोग्राम को निष्पादित करने के लिए एक आवरण हो सकती है, या 2. KeepAlive.pl टेबल की तालिका को पार्स कर सकती है सक्रिय सिस्टम प्रक्रियाएं (CPAN के प्रोक :: प्रोसेसटेबल के साथ) संबंधित प्रक्रिया और इसकी सहायता को खोजने का प्रयास करने के लिए)।
ईथर

1

आप Monit को भी आज़मा सकते हैं । मोनेट एक ऐसी सेवा है जो अन्य सेवाओं पर निगरानी और रिपोर्ट करती है। हालांकि यह मुख्य रूप से रनटाइम समस्याओं के बारे में सूचित करने (ईमेल और एसएमएस के माध्यम से) के रूप में उपयोग किया जाता है, यह भी कर सकता है कि यहां अन्य सुझावों में से अधिकांश ने क्या वकालत की है। यह प्रोग्रामों को शुरू और बंद कर सकता है, ईमेल भेज सकता है, अन्य स्क्रिप्ट्स आरंभ कर सकता है और आउटपुट का एक लॉग बनाए रख सकता है जिसे आप उठा सकते हैं। इसके अलावा, मैंने पाया है कि ठोस प्रलेखन के बाद से इसे स्थापित करना और बनाए रखना आसान है।


1

आप अमर होने की कोशिश कर सकते हैं यह एक * निक्स क्रॉस-प्लेटफ़ॉर्म (ओएस अज्ञेयवादी) पर्यवेक्षक है।

MacOS पर एक त्वरित प्रयास के लिए:

brew install immortal

मामले में आप FreeBSD का उपयोग कर रहे हैं बंदरगाहों से या pkg का उपयोग :

pkg install immortal

के लिए लिनक्स precompiled binaries या स्रोत से डाउनलोड करके: https://immortal.run/source/

आप इसे इस तरह से उपयोग कर सकते हैं:

immortal -l /var/log/date.log date

या एक विन्यास YAML फ़ाइल द्वारा जो आपको अधिक विकल्प देता है, उदाहरण के लिए:

cmd: date
log:
    file: /var/log/date.log
    age: 86400 # seconds
    num: 7     # int
    size: 1    # MegaBytes
    timestamp: true # will add timesamp to log

यदि आप एक अलग फ़ाइल में भी मानक त्रुटि आउटपुट रखना चाहते हैं तो आप कुछ इस तरह का उपयोग कर सकते हैं:

cmd: date
log:
    file: /var/log/date.log
    age: 86400 # seconds
    num: 7     # int
    size: 1    # MegaBytes
stderr:
    file: /var/log/date-error.log
    age: 86400 # seconds
    num: 7     # int
    size: 1    # MegaBytes
    timestamp: true # will add timesamp to log

0

मैंने अन्य उत्तर पर सुधारों की एक श्रृंखला बनाई है ।

  1. इस स्क्रिप्ट से स्टडआउट पूरी तरह से अपने बच्चे से आने वाले स्टडआउट से बना है, क्योंकि यह पता चलता है कि कमांड पहले से ही चलाया जा रहा है।
  2. समाप्त होने पर अपने पिडफाइल के बाद साफ करता है
  3. वैकल्पिक विन्यास समयबाह्य अवधि (किसी भी सकारात्मक संख्यात्मक तर्क को स्वीकार करता है, को भेजता है sleep )
  4. पर शीघ्र उपयोग -h
  5. एकल आदेश निष्पादन के बजाय मनमाना कमांड निष्पादन। अंतिम arg या शेष args (यदि एक से अधिक अंतिम arg) को भेजा जाता हैeval , तो आप इस स्क्रिप्ट को अंतिम arg (या अनुगामी args) के रूप में भेजने के लिए किसी भी प्रकार के शेल स्क्रिप्ट को एक स्ट्रिंग के रूप में निर्मित कर सकते हैं।
  6. तर्क गिनती तुलना के -ltबजाय के साथ किया जाता है<

यहाँ स्क्रिप्ट है:

#!/bin/sh

# this script builds a mini-daemon, which isn't a real daemon because it
# should die when the owning terminal dies, but what makes it useful is
# that it will restart the command given to it when it completes, with a
# configurable timeout period elapsing before doing so.

if [ "$1" = '-h' ]; then
    echo "timeout defaults to 1 sec.\nUsage: $(basename "$0") sentinel-pidfile [timeout] command [command arg [more command args...]]"
    exit
fi

if [ $# -lt 2 ]; then
    echo "No command given."
    exit
fi

PIDFILE=$1
shift

TIMEOUT=1
if [[ $1 =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
        TIMEOUT=$1
        [ $# -lt 2 ] && echo "No command given (timeout was given)." && exit
        shift
fi

echo "Checking pid in file ${PIDFILE}." >&2

#Check to see if process running.
if [ -f "$PIDFILE" ]; then
    PID=$(< $PIDFILE)
    if [ $? = 0 ]; then
        ps -p $PID >/dev/null 2>&1
        if [ $? = 0 ]; then
            echo "This script is (probably) already running as PID ${PID}."
            exit
        fi
    fi
fi

# Write our pid to file.
echo $$ >$PIDFILE

cleanup() {
        rm $PIDFILE
}
trap cleanup EXIT

# Run command until we're killed.
while true; do
    eval "$@"
    echo "I am $$ and my child has exited; restart in ${TIMEOUT}s" >&2
    sleep $TIMEOUT
done

उपयोग:

$ term-daemonize.sh pidfilefortesting 0.5 'echo abcd | sed s/b/zzz/'
Checking pid in file pidfilefortesting.
azzzcd
I am 79281 and my child has exited; restart in 0.5s
azzzcd
I am 79281 and my child has exited; restart in 0.5s
azzzcd
I am 79281 and my child has exited; restart in 0.5s
^C

$ term-daemonize.sh pidfilefortesting 0.5 'echo abcd | sed s/b/zzz/' 2>/dev/null
azzzcd
azzzcd
azzzcd
^C

सावधान रहें कि यदि आप अलग-अलग निर्देशिकाओं से इस स्क्रिप्ट को चलाते हैं, तो यह अलग-अलग pidfiles का उपयोग कर सकता है और किसी भी मौजूदा चल रहे उदाहरणों का पता नहीं लगा सकता है। चूंकि यह एक तर्क के माध्यम से प्रदान की गई पंचांग कमांड को चलाने और पुनः आरंभ करने के लिए डिज़ाइन किया गया है, इसलिए यह जानने का कोई तरीका नहीं है कि क्या कुछ पहले से ही शुरू हो गया है, क्योंकि यह कहना है कि क्या यह एक ही कमांड है या नहीं? किसी चीज के केवल एक उदाहरण को चलाने के इस प्रवर्तन पर सुधार करने के लिए, स्थिति के लिए विशिष्ट समाधान की आवश्यकता होती है।

इसके अलावा, इसके लिए एक उचित डेमन के रूप में कार्य करने के लिए, आपको अन्य उत्तर उल्लेखों के रूप में (नंगे न्यूनतम पर) नूप का उपयोग करना होगा। मैंने इस प्रक्रिया को प्राप्त होने वाले संकेतों के लिए कोई लचीलापन प्रदान करने का कोई प्रयास नहीं किया है।

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

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