Init स्क्रिप्ट से डेमन के रूप में मनमाना कार्यक्रम चलाना


10

मुझे Red Hat में सेवा के रूप में एक प्रोग्राम स्थापित करने की आवश्यकता है। यह खुद को बैकग्राउंड नहीं करता है, इसकी PID फाइल को प्रबंधित करता है, या अपने लॉग का प्रबंधन करता है। यह सिर्फ STDOUT और STDERR को चलाता है और प्रिंट करता है।

गाइड के रूप में मानक init स्क्रिप्ट का उपयोग करना, मैंने निम्नलिखित विकसित किया है:

#!/bin/bash
#
#   /etc/rc.d/init.d/someprog
#
# Starts the someprog daemon
#
# chkconfig: 345 80 20
# description: the someprog daemon
# processname: someprog
# config: /etc/someprog.conf

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

prog="someprog"
exec="/usr/local/bin/$prog"
[ -e "/etc/sysconfig/$prog" ] && . "/etc/sysconfig/$prog"
lockfile="/var/lock/subsys/$prog"
RETVAL=0

check() {
    [ `id -u` = 0 ] || exit 4
    test -x "$exec" || exit 5
}

start() {
    check
    if [ ! -f "$lockfile" ]; then
        echo -n $"Starting $prog: " 
        daemon --user someproguser "$exec"
        RETVAL=$?
        [ $RETVAL -eq 0 ] && touch "$lockfile"
        echo
    fi
    return $RETVAL
}

stop() {
    check
    echo -n $"Stopping $prog: "
    killproc "exec"
    RETVAL=$?
    [ $RETVAL -eq 0 ] && rm -f "$lockfile"
    echo
    return $RETVAL
}

restart() {
    stop
    start
}   

case "$1" in
start)
    start
    ;;
stop)
    stop
    ;;
restart)
    restart
    ;;
status)
    status "$prog"
    RETVAL=$?
    ;;
*)
    echo $"Usage: $0 {start|stop|restart|status}"
    RETVAL=2
esac

exit $RETVAL

यह हो सकता है कि मेरी गलती /etc/init.d में मौजूद कुछ स्क्रिप्ट को कॉपी-पेस्ट और संशोधित करने की थी। किसी भी मामले में, परिणामी सेवा अजीब व्यवहार करती है:

  • जब मैं इसे service someprog startटर्मिनल के लिए प्रोग्राम प्रिंट के साथ शुरू करता हूं और कमांड पूरा नहीं होता है।
  • यदि मैं CTRL-C करता हूं, तो यह "सत्र समाप्त हो जाता है, शेल को मारता है ... मारा जाता है। विफल"। मुझे अपना शेल फिर से वापस पाने के लिए ऐसा करना होगा।
  • अब जब मैं service someprog statusइसे चलाता हूं तो यह कहता है कि यह चल रहा है और इसकी पीआईडी ​​को सूचीबद्ध करता है। मैं इसे देख सकता हूं psइसलिए यह चल रहा है।
  • अब जब मैं दौड़ता हूं तो service someprog stopयह रुकने में विफल रहता है। मैं सत्यापित कर सकता हूं कि यह अभी भी साथ चल रहा है ps

मुझे क्या बदलने की आवश्यकता है ताकि someprogपृष्ठभूमि पर भेजा जाए और एक सेवा के रूप में प्रबंधित किया जाए?

संपादित करें: मुझे अब संबंधित प्रश्नों के एक जोड़े का पता चला है, दोनों में से कोई भी वास्तविक उत्तर के अलावा "कुछ और न करें":

संपादित करें: डबल-फोर्किंग के इस जवाब से मेरी समस्या हल हो गई होगी, लेकिन अब मेरा प्रोग्राम खुद डबल-फोर्क्स और वह काम करता है: https://stackoverflow.com/a/9646251/898699


क्या आप कार्यक्रम "डेमॉन" उपयोगिता के साथ शुरू कर रहे हैं जो कि लिब्स्लैक द्वारा प्रदान किया गया है। libslack.org/daemon/#documentation इस मामले में कार्यक्रम को डेमन-एन नाम - स्टॉप के रूप में रोका जा सकता है। इसके अलावा, आउटपुट को पुनर्निर्देशित करने का प्रयास करें (जब प्रोग्राम शुरू हो) एक फ़ाइल या / dev / null और चेक करें।
अंकित

2
रेडहैट के अपने संस्करण पर निर्भर, आप बस ऊपर की ओर के लिए एक साधारण आवरण बना सकते हैं और इसे सीधे ऊपर की ओर बुला सकते हैं। तब upstart आपके लिए सेवा का प्रबंधन करेगा। यह हालांकि एक EL6 बात है।
मैथ्यू इफ

जवाबों:


1

कमांड "पूरा नहीं करता है" क्योंकि daemonफ़ंक्शन आपके एप्लिकेशन को आपके लिए पृष्ठभूमि में नहीं चलाता है। आपको &अपनी daemonकमांड के अंत में इस तरह से जोड़ना होगा :

daemon --user someproguser $exec &

यदि आप someprogसंभाल नहीं करते हैं SIGHUP, तो आपको nohupयह सुनिश्चित करने के लिए कमांड को चलाना चाहिए कि आपकी प्रक्रिया प्राप्त नहीं होगी SIGHUPजो कि पेरेंट शेल के बाहर निकलने पर आपकी प्रक्रिया को बाहर निकलने के लिए कहती है। यह इस तरह दिखेगा:

daemon --user someproguser "nohup $exec" &

अपने stopकार्य में, killproc "exec"अपने कार्यक्रम को रोकने के लिए कुछ भी नहीं कर रहा है। इसे ऐसे पढ़ना चाहिए:

killproc $exec

killprocइसे ठीक से रोकने के लिए आपके आवेदन के लिए पूर्ण पथ की आवश्यकता है। मुझे killprocअतीत में कुछ परेशानी हुई है, इसलिए आप पीआईडीआईडी ​​में पीआईडी ​​को भी मार सकते हैं, आपको someprogइस तरह से कुछ के साथ पीआईडी लिखना चाहिए :

cat $pidfile | xargs kill

आप इस तरह PIDFILE लिख सकते हैं:

ps aux | grep $exec | grep -v grep | tr -s " " | cut -d " " -f2 > $pidfile

जहां $pidfileअंक के लिए /var/run/someprog.pid

यदि आप अपने stopफ़ंक्शन पर [OK] या [FAILED] चाहते हैं, तो आपको successऔर से failureकार्यों का उपयोग करना चाहिए /etc/rc.d/init.d/functions। आपको startफ़ंक्शन में इनकी आवश्यकता नहीं है क्योंकि daemonआपके लिए उपयुक्त कॉल है।

आपको केवल रिक्त स्थान के साथ स्ट्रिंग के आसपास उद्धरणों की भी आवश्यकता है। हालाँकि, यह एक स्टाइल चॉइस है, इसलिए यह आपके ऊपर है।

ये सभी परिवर्तन इस तरह दिखते हैं:

#!/bin/bash
#
#   /etc/rc.d/init.d/someprog
#
# Starts the someprog daemon
#
# chkconfig: 345 80 20
# description: the someprog daemon
# processname: someprog
# config: /etc/someprog.conf

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

prog=someprog
exec=/usr/local/bin/$prog
[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog
lockfile=/var/lock/subsys/$prog
pidfile=/var/run/$prog
RETVAL=0

check() {
    [ `id -u` = 0 ] || exit 4
    test -x $exec || exit 5
}

start() {
    check
    if [ ! -f $lockfile ]; then
        echo -n $"Starting $prog: " 
        daemon --user someproguser "nohup $exec" &
        RETVAL=$?
        if [ $RETVAL -eq 0 ]; then
          touch $lockfile
          ps aux | grep $exec | grep -v grep | tr -s " " | cut -d " " -f2 > $pidfile
        fi
        echo
    fi
    return $RETVAL
}

stop() {
    check
    echo -n $"Stopping $prog: "
    killproc $exec && cat $pidfile | kill
    RETVAL=$?
    if [ $RETVAL -eq 0 ]; then
      rm -f $lockfile
      rm -f $pidfile
      success; echo
    else
      failure; echo
    fi
    echo
    return $RETVAL
}

restart() {
    stop
    start
}   

case "$1" in
start)
    start
    ;;
stop)
    stop
    ;;
restart)
    restart
    ;;
status)
    status $prog
    RETVAL=$?
    ;;
*)
    echo $"Usage: $0 {start|stop|restart|status}"
    RETVAL=2
esac

exit $RETVAL

खेद है कि आपको उचित उत्तर पाने में लगभग 4.5 वर्ष लग गए।
स्टूपॉर्मन

-1

यदि यह आपका कार्यक्रम है, तो कृपया इसे एक उचित डेमॉन के रूप में लिखें। खासकर यदि इसके पुनर्वितरण के लिए। :)

आप मॉनेट की कोशिश कर सकते हैं । या शायद रनिट या डेमोंटोल्स जैसे कुछ। उन शक्तिशाली के पास आसानी से उपलब्ध पैकेज नहीं हैं। डेमोंटोलस डीजेबी से है, अगर यह आपके निर्णय को प्रभावित करता है (किसी भी दिशा में)।


-1

मैंने कुछ और शोध किए हैं और ऐसा प्रतीत होता है कि उत्तर "आप ऐसा नहीं कर सकते।" चलाए जाने वाले कार्यक्रम को वास्तव में खुद को ठीक से निर्धारित करना चाहिए: कांटा और इसके मानक फ़ाइलहैंड्स को अलग करना, टर्मिनल से अलग करना, और एक नया सत्र शुरू करना।

संपादित करें: जाहिरा तौर पर मैं गलत हूं - डबल फोर्किंग काम करेगा। https://stackoverflow.com/a/9646251/898699


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