Ausführen eines beliebigen Programms als Daemon über das Init-Skript

10

Ich muss ein Programm als Dienst in Red Hat installieren. Es wird kein Hintergrund erstellt, keine PID-Datei verwaltet oder keine eigenen Protokolle verwaltet. Es wird nur ausgeführt und in STDOUT und STDERR gedruckt.

Unter Verwendung der Standard-Init-Skripte als Leitfaden habe ich Folgendes entwickelt:

#!/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

Es kann sein, dass mein Fehler darin bestand, einige der vorhandenen Skripte in /etc/init.d zu kopieren, einzufügen und zu ändern. In jedem Fall verhält sich der resultierende Dienst seltsam:

  • Wenn ich es mit service someprog startdem Programm starte, wird es auf dem Terminal gedruckt und der Befehl wird nicht ausgeführt.
  • Wenn ich STRG-C drücke, wird "Sitzung beendet, Shell beendet ... ... getötet. FEHLGESCHLAGEN" ausgegeben. Ich muss dies tun, um meine Shell-Eingabeaufforderung wieder zu erhalten.
  • Wenn ich service someprog statuses jetzt starte , sagt es, dass es läuft und listet seine PID auf. Ich kann es sehen, psdamit es läuft.
  • Wenn ich jetzt laufe service someprog stop, hört es nicht auf. Ich kann überprüfen, ob es noch läuft ps.

Was muss ich ändern, damit someproges in den Hintergrund gesendet und als Service verwaltet wird?

Bearbeiten: Ich habe jetzt ein paar verwandte Fragen gefunden, keine mit einer anderen tatsächlichen Antwort als "etwas anderes tun":

Bearbeiten: Diese Antwort auf Double-Forking hat möglicherweise mein Problem gelöst, aber jetzt hat mein Programm selbst Double-Forks und das funktioniert: /programming//a/9646251/898699

Baron Schwartz
quelle
Starten Sie das Programm mit dem von libslack bereitgestellten Dienstprogramm "daemon"? libslack.org/daemon/#documentation In diesem Fall kann das Programm als Daemon -n name --stop gestoppt werden. Versuchen Sie auch, die Ausgabe (beim Starten des Programms) in eine Datei oder / dev / null umzuleiten, und überprüfen Sie dies.
Ankit
2
Abhängig von Ihrer Redhat-Version können Sie im Upstart einfach einen einfachen Wrapper dafür erstellen und ihn direkt im Upstart aufrufen. Dann verwaltet upstart den Dienst für Sie. Dies ist jedoch eine EL6-Sache.
Matthew Ife

Antworten:

1

Der Befehl "wird nicht abgeschlossen", da die daemonFunktion Ihre Anwendung für Sie nicht im Hintergrund ausführt. Sie müssen &am Ende Ihres daemonBefehls wie folgt ein hinzufügen :

daemon --user someproguser $exec &

Wenn someprogdies nicht der Fall ist SIGHUP, sollten Sie den Befehl mit ausführen, nohupum sicherzustellen, dass Ihr Prozess nicht empfangen wird. SIGHUPDadurch wird Ihr Prozess angewiesen, beim Beenden der übergeordneten Shell zu beenden. Das würde so aussehen:

daemon --user someproguser "nohup $exec" &

Tut in Ihrer stopFunktion killproc "exec"nichts, um Ihr Programm zu stoppen. Es sollte so lauten:

killproc $exec

killprocerfordert den vollständigen Pfad zu Ihrer Anwendung, um sie ordnungsgemäß zu stoppen. Ich hatte killprocin der Vergangenheit einige Probleme damit , daher können Sie auch einfach die PID in der PIDFILE löschen, in die Sie die PID schreiben sollten someprog, mit so etwas:

cat $pidfile | xargs kill

Sie können die PIDFILE folgendermaßen schreiben:

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

wo $pidfilePunkte zu /var/run/someprog.pid.

Wenn Sie [OK] oder [FAILED] für Ihre stopFunktion wünschen , sollten Sie die Funktionen successund failurevon verwenden /etc/rc.d/init.d/functions. Sie benötigen diese nicht in der startFunktion, da sie daemondie für Sie geeignete aufruft.

Sie benötigen außerdem nur Anführungszeichen um Zeichenfolgen mit Leerzeichen. Es ist jedoch eine Stilwahl, also liegt es an Ihnen.

Alle diese Änderungen sehen folgendermaßen aus:

#!/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
Stuporman
quelle
Es tut uns leid, dass Sie fast 4,5 Jahre gebraucht haben, um eine richtige Antwort zu erhalten.
Stuporman
-1

Wenn dies Ihr Programm ist, schreiben Sie es bitte als richtigen Daemon. Besonders wenn es zur Umverteilung ist. :) :)

Sie könnten versuchen, zu überwachen . Oder vielleicht so etwas wie Runit oder Daemontools. Diese mächtigen haben nicht sofort verfügbare Pakete. Daemontools ist von DJB, wenn dies Ihre Entscheidung beeinflusst (in beide Richtungen).

gestürzter Wagen
quelle
-1

Ich habe weitere Nachforschungen angestellt und es scheint, dass die Antwort lautet: "Das können Sie nicht tun." Das auszuführende Programm muss sich tatsächlich ordnungsgemäß dämonisieren: seine Standard-Dateihandles aufteilen und trennen, vom Terminal trennen und eine neue Sitzung starten.

Edit: anscheinend irre ich mich - Double Forking würde funktionieren. /programming//a/9646251/898699

Baron Schwartz
quelle
Sie können dies mit upstart tun, wie in den Kommentaren angegeben.