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すると、実行中であると表示され、そのPIDがリストされます。私はそれを見ることができるpsので、走っています。
  • 今実行するservice someprog stopと、停止に失敗します。で引き続き実行されていることを確認できpsます。

someprogバックグラウンドに送信してサービスとして管理するために何を変更する必要がありますか?

編集:私は今、いくつかの関連する質問を見つけましたが、どちらも「何か他のことをする」以外の実際の答えはありません:

編集:ダブルフォークに関するこの答えは私の問題を解決したかもしれませんが、今私のプログラム自体はダブルフォークであり、それは機能します:https//stackoverflow.com/a/9646251/898699


libslackが提供する「デーモン」ユーティリティを使用してプログラムを起動していますか。libslack.org/daemon/#documentationこの場合、プログラムはdaemon -n name --stopとして停止できます。また、(プログラムの起動時に)出力をファイルまたは/ dev / nullにリダイレクトして確認してください。
Ankit 2013年

2
Redhatのバージョンに応じて、upstartで単純なラッパーを作成し、upstartで直接呼び出すことができます。その後、upstartがサービスを管理します。これはEL6のものです。
マシューイフェ2013年

回答:


1

daemon関数はバックグラウンドでアプリケーションを実行しないため、コマンドは「完了しません」。次のよう&に、daemonコマンドの最後にを追加する必要があります。

daemon --user someproguser $exec &

someprogがを処理しない場合はSIGHUP、コマンドを実行して、親シェルが終了したときにプロセスに終了するnohupようSIGHUPに指示するプロセスが受信しないようにする必要があります。これは次のようになります。

daemon --user someproguser "nohup $exec" &

あなたにはstop機能、killproc "exec"あなたのプログラムを停止するために何もしていません。それはそう読むべきです:

killproc $exec

killproc正しく停止するには、アプリケーションへのフルパスが必要です。私はkillproc過去にいくつかの問題を抱えていたのでsomeprog、次のようなものでPIDFILE のPIDを書き込む必要があるPIDFILEのPIDを強制終了することもできます。

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 2017

-1

これがあなたのプログラムなら、適切なデーモンとして書いてください。特に再配布の場合。:)

あなたはmonitを試すかもしれません。または多分runitまたはdaemontoolsのようなもの。それらはすぐに利用できるパッケージを持っていないかもしれません。DaemontoolsがDJBからのものである場合、それが決定に影響を与える場合(どちらの方向でも)。


-1

私はもう少し調査を行いましたが、答えは「あなたはそれを行うことができない」です。実行するプログラムは、実際にそれ自体を適切にデーモン化する必要があります。フォークして標準ファイルハンドルを切り離し、端末から切り離し、新しいセッションを開始します。

編集:明らかに私は間違っています-ダブルフォークが機能します。/programming//a/9646251/898699


コメントに記載されているように、upstartを使用してそれを行うことができます。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.