การรันโปรแกรมโดยพลการเป็น daemon จากสคริปต์ 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 มันจะพิมพ์ "เซสชันสิ้นสุดลงฆ่าเชลล์ ... ... kill. FAILED" ฉันต้องทำสิ่งนี้เพื่อให้ shell prompt กลับมาอีกครั้ง
  • ตอนนี้เมื่อฉันเรียกใช้service someprog statusมันบอกว่ามันกำลังทำงานอยู่และแสดงรายการ PID ของมัน ฉันสามารถดูได้ในpsเพื่อให้มันทำงาน
  • ตอนนี้เมื่อฉันเรียกใช้service someprog stopมันล้มเหลวในการหยุด ฉันสามารถตรวจสอบได้ว่ามันยังทำงานpsอยู่

ฉันต้องเปลี่ยนอะไรจึงsomeprogจะส่งไปยังพื้นหลังและจัดการเป็นบริการ

แก้ไข: ตอนนี้ฉันได้พบคำถามสองสามคำถามที่เกี่ยวข้องกับพวกเขาไม่มีคำตอบจริงนอกเหนือจาก "ทำอย่างอื่น":

แก้ไข: คำตอบสำหรับการตีสองครั้งนี้อาจช่วยแก้ไขปัญหาของฉันได้ แต่ตอนนี้โปรแกรมของฉันใช้การกดสองครั้งและทำงานได้: https://stackoverflow.com/a/9646251/898699


คุณกำลังเริ่มต้นโปรแกรมด้วยยูทิลิตี้ "daemon" ที่จัดทำโดย libslack libslack.org/daemon/#documentationในกรณีนี้โปรแกรมสามารถหยุดการทำงานเป็น daemon -n name --stop นอกจากนี้ให้ลองเปลี่ยนเส้นทางเอาต์พุต (เมื่อเริ่มต้นโปรแกรม) ไปยังไฟล์หรือ / dev / null และตรวจสอบ
Ankit

2
ขึ้นอยู่กับรุ่น redhat ของคุณคุณสามารถทำ wrapper ง่าย ๆ สำหรับมันในการพุ่งพรวดและโทรมันในพุ่งพรวดโดยตรง จากนั้นพุ่งพรวดจะจัดการบริการสำหรับคุณ นี่คือสิ่งที่ EL6
Matthew Ife

คำตอบ:


1

คำสั่ง "ไม่สมบูรณ์" เพราะdaemonฟังก์ชั่นไม่ได้เรียกใช้แอปพลิเคชันของคุณในพื้นหลังสำหรับคุณ คุณจะต้องเพิ่มคำสั่ง&ต่อท้ายdaemonดังนี้:

daemon --user someproguser $exec &

หากsomeprogไม่จัดการSIGHUPคุณควรรันคำสั่งด้วยnohupเพื่อให้แน่ใจว่ากระบวนการของคุณจะไม่ได้รับSIGHUPซึ่งจะบอกให้กระบวนการของคุณออกเมื่อเชลล์พาเรนออกจาก ที่จะมีลักษณะเช่นนี้:

daemon --user someproguser "nohup $exec" &

ในstopฟังก์ชั่นของคุณkillproc "exec"ไม่ได้ทำอะไรเพื่อหยุดโปรแกรมของคุณ ควรอ่านดังนี้:

killproc $exec

killprocต้องการเส้นทางแบบเต็มไปยังแอปพลิเคชันของคุณเพื่อหยุดการทำงานอย่างถูกต้อง ฉันเคยมีปัญหากับkillprocในอดีตดังนั้นคุณสามารถฆ่า PID ใน PIDFILE ที่คุณควรจะเขียนsomeprogPID ของด้วยเช่นนี้:

cat $pidfile | xargs kill

คุณสามารถเขียน PIDFILE เช่นนี้:

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

ที่ชี้ไปยัง$pidfile/var/run/someprog.pid

หากคุณต้องการ [OK] หรือ [FAILED] ในstopฟังก์ชั่นที่คุณควรใช้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 ปีในการรับคำตอบที่เหมาะสม
Stuporman

-1

หากนี่คือโปรแกรมของคุณโปรดเขียนเป็นภูตที่ถูกต้อง โดยเฉพาะอย่างยิ่งหากมีการแจกจ่ายซ้ำ :)

คุณอาจลองmonit หรืออาจเป็นสิ่งที่ชอบ runit หรือ daemontools อันยิ่งใหญ่ที่ไม่ได้มีแพคเกจพร้อมใช้งาน Daemontools มาจาก DJB หากสิ่งนั้นมีอิทธิพลต่อการตัดสินใจของคุณ (ในทิศทางใดทิศทางหนึ่ง)


-1

ฉันได้ทำการวิจัยเพิ่มเติมแล้วและดูเหมือนว่าคำตอบคือ "คุณทำอย่างนั้นไม่ได้" โปรแกรมที่จะเรียกใช้จะต้อง daemonize ตัวเองอย่างถูกต้อง: fork และแยก filehandles มาตรฐานออกจาก terminal และเริ่มเซสชันใหม่

แก้ไข: เห็นได้ชัดว่าฉันผิดการฟอร์กกิ้งสองครั้งจะได้ผล https://stackoverflow.com/a/9646251/898699


คุณสามารถทำได้โดยใช้พุ่งพรวดตามที่ระบุไว้ในความคิดเห็น
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.