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 인 경우 "세션이 종료되었습니다. 쉘을 종료하는 중입니다 ... ... killed. FAILED"를 표시합니다. 쉘 프롬프트를 다시 받으려면이 작업을 수행해야합니다.
  • 이제 내가 실행할 때 service someprog status실행 중이라고 말하고 PID를 나열합니다. 나는 그것을 볼 수있어서 ps실행 중입니다.
  • 이제 내가 실행할 때 service someprog stop멈추지 않습니다. 여전히 실행 중임을 확인할 수 있습니다 ps.

someprog백그라운드로 전송되고 서비스로 관리 되도록 변경하려면 무엇이 필요 합니까?

편집 : 이제 몇 가지 관련 질문을 찾았습니다. "다른 일을"하는 것 이외의 실제 답변은 없습니다.

편집 : 이중 분기에 대한이 답변은 내 문제를 해결했을 수도 있지만 이제는 프로그램 자체가 이중 분기되고 작동합니다. https://stackoverflow.com/a/9646251/898699


libslack에서 제공하는 "daemon"유틸리티를 사용하여 프로그램을 시작하고 있습니까? libslack.org/daemon/#documentation 이 경우 프로그램은 daemon -n name --stop으로 중지 될 수 있습니다. 또한 출력을 (프로그램을 시작할 때) 파일 또는 / dev / null로 리디렉션하고 확인하십시오.
Ankit

2
Redhat 버전에 따라 시작시 간단한 래퍼를 만들어서 시작시 직접 호출 할 수 있습니다. 그러면 upstart가 서비스를 관리합니다. 이것은 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과거에 문제가 있었 으므로 PIDFILE에서 PID를 죽일 수 있습니다. someprogPID를 다음과 같이 작성해야합니다 .

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 년이 걸렸습니다.
Stuporman

-1

이것이 귀하의 프로그램 인 경우 적절한 데몬으로 작성하십시오. 특히 재배포 용인 경우. :)

monit을 시도 할 수 있습니다 . 또는 runit 또는 daemontools와 같은 것일 수 있습니다. 그것들은 쉽게 구할 수있는 패키지를 가지고 있지 않습니다. Daemontools는 DJB에서 나왔습니다.


-1

나는 더 많은 연구를 해왔으며 그 대답은 "당신은 그렇게 할 수 없습니다"라고 보입니다. 실행할 프로그램은 실제로 자신을 올바르게 데몬해야합니다. 표준 파일 핸들을 포크 및 분리하고 터미널에서 분리하고 새 세션을 시작해야합니다.

편집 : 분명히 나는 ​​틀렸다-이중 포크가 작동합니다. https://stackoverflow.com/a/9646251/898699


주석에 명시된대로 upstart를 사용하여이를 수행 할 수 있습니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.