Comment puis-je exécuter un script shell en tant que démon sous Redhat?


12

J'ai un script shell, qui est essentiellement une ligne avec une journalisation, que j'essaie d'exécuter à partir d'un script init. J'utilise la daemonfonction à l'intérieur de /etc/init.d/functionspour l'exécuter, car Redhat ne semble pas être start-stop-daemondisponible. Lorsque j'appelle le script init ( /etc/init.d/script start), il reste au premier plan, plutôt que de terminer et de laisser le processus en cours. Quelle est la bonne façon pour moi de faire démoniser ce script?

Script à exécuter:

# conf file where variables are defined
. /etc/script.conf

echo "Starting..." | logger -i
echo "Monitoring $LOG_LOCATION." | logger -i
echo "Sending to $MONITOR_HOST:$MONITOR_PORT." | logger -i

tail -n 1 -F $LOG_LOCATION |
grep WARN --line-buffered  |
/usr/bin/nc -vv $MONITOR_HOST $MONITOR_PORT 2>&1 |
logger -i

script d'initialisation:

#!/bin/bash


# Source Defaults
. /etc/default/script

# Source init functions
. /etc/init.d/functions

prog=/usr/local/bin/script.sh

[ -f /etc/script.conf ] || exit 1

RETVAL=0

start()
{
    # Quit if disabled
    if ! $ENABLED; then
            echo "Service Disabled in /etc/default/script"
            exit 1
    fi

    echo "Starting $prog"

    daemon $prog

    RETVAL=$?

    return $RETVAL
}

stop ()
{
    echo -n $"Stopping $prog: "
    killproc $prog

    RETVAL=$?

    return $RETVAL
}

reload()
{
    echo "Reload command is not implemented for this service."
    return $RETVAL
}

restart()
{
    stop
    start
}

condrestart()
{
    echo "Not Implemented."
}

# See how we were called.
case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    status)
        status $prog
        ;;
    restart)
        restart
        ;;
    reload)
        reload
        ;;
    condrestart)
        condrestart
        ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|reload}"
        RETVAL=1
esac

~ 20 dernières lignes d'exécution avec bash -vx:

+ case "$1" in
+ start
+ true
+ echo 'Starting /usr/local/bin/script.sh'
Starting /usr/local/bin/script.sh
+ daemon /usr/local/bin/script.sh
+ local gotbase= force=
+ local base= user= nice= bg= pid=
+ nicelevel=0
+ '[' /usr/local/bin/script.sh '!=' /usr/local/bin/script.sh ']'
+ '[' -z '' ']'
+ base=script.sh
+ '[' -f /var/run/script.sh.pid ']'
+ '[' -n '' -a -z '' ']'
+ ulimit -S -c 0
+ '[' -n '' ']'
+ '[' color = verbose -a -z '' ']'
+ '[' -z '' ']'
+ initlog -q -c /usr/local/bin/script.sh

Il me semble utile d'exécuter ce script bash -vx ...et de publier les dernières lignes afin que nous puissions voir ce qui reste au premier plan.
Hauke ​​Laging

1
Ne vous embêtez pas à utiliser ce droit et continuez daemon, il existe également un package RPM . Btw, il existe de nombreux outils de surveillance des journaux ( commencez ici ).
sr_

Hauke, tu veux dire utiliser une première ligne de #!/bin/bash -vx? J'ai essayé de le faire, mais cela ne produisait pas la même sortie du script init que si j'exécutais le script shell directement.
bshacklett le

@bshacklett vous pouvez examiner la fonction de n'importe quel script d'initialisation (tout script shell en fait) en l'exécutant explicitement avec bash -vx, c'est-à-dire. bash -vx /etc/init.d/script start.
sr_

1
@bshacklett Wrt logs, j'examinerais de plus près logstash . Le magasin peut être alimenté en journaux directement depuis Log4j, mais l'agent logstash peut également surveiller les fichiers journaux
sr_

Réponses:


2

J'ai trouvé un script sur http://www.linuxforums.org/forum/programming-scripting/190279-daemon-etc-init-d-functions-does-not-return-launching-process.html#post897522 dont j'ai pu à adapter à mes besoins. Il suit manuellement le PID et crée un fichier PID à l'aide pidof. J'ai fini par devoir le modifier pour l'utiliser pgrepcar je n'ai pidofpas pu voir le PID de mon script. Après cette modification, cela a bien fonctionné. * Remarque, pgrep ne semble fonctionner que si le nom complet du script comporte moins de 15 caractères

Voici ce que j'ai fini avec:

#!/bin/bash
#
# 
#
# Start on runlevels 3, 4 and 5. Start late, kill early.
# chkconfig: 345 95 05
#
#
#!/bin/bash

# absolute path to executable binary
progpath='/usr/local/bin/script.sh'

# arguments to script
opts=''

# binary program name
prog=$(basename $progpath)

# pid file
pidfile="/var/run/${prog}.pid"

# make sure full path to executable binary is found
! [ -x $progpath ] && echo "$progpath: executable not found" && exit 1

eval_cmd() {
  local rc=$1
  if [ $rc -eq 0 ]; then
    echo '[  OK  ]'
  else
    echo '[FAILED]'
  fi
  return $rc
}

start() {
  # see if running
  local pids=$(pgrep $prog)

  if [ -n "$pids" ]; then
    echo "$prog (pid $pids) is already running"
    return 0
  fi
  printf "%-50s%s" "Starting $prog: " ''
  $progpath $opts &

  # save pid to file if you want
  echo $! > $pidfile

  # check again if running
  pgrep $prog >/dev/null 2>&1
  eval_cmd $?
}

stop() {
  # see if running
  local pids=$(pgrep $prog)

  if [ -z "$pids" ]; then
    echo "$prog not running"
    return 0
  fi
  printf "%-50s%s" "Stopping $prog: " ''
  rm -f $pidfile
  kill -9 $pids
  eval_cmd $?
}

status() {
  # see if running
  local pids=$(pgrep $prog)

  if [ -n "$pids" ]; then
    echo "$prog (pid $pids) is running"
  else
    echo "$prog is stopped"
  fi
}

case $1 in
  start)
    start
    ;;
  stop)
    stop
    ;;
  status)
    status
    ;;
  restart)
    stop
    sleep 1
    start
    ;;
  *)
    echo "Usage: $0 {start|stop|status|restart}"
    exit 1
esac

exit $?

0

Je ne connais pas Redhat mais daemon $prog &ça me semble étrange. S'il existe déjà une fonction de démonétisation, pourquoi serait-il nécessaire (et utile) de mettre cette fonction elle-même en arrière-plan? Essayez donc sans le &.


4
Ce n'est pas faux. /etc/init.d/functionsdéfinit une daemonfonction qui s'attend à ce que son argument se démonifie, il ne s'occupe que de choses comme changer l'utilisateur, paramétrer ulimits, vérifier (pas créer!) un fichier pid ... Le meilleur usage de cette daemonfonction est de le remplacer par libslackdaemon ;)
sr_

Je suis désolé, le & était là à un moment donné lors du dépannage. Je ne voulais pas l'inclure dans ce post.
bshacklett
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.