¿Cómo puedo ejecutar un script de shell como demonio en Redhat?

12

Tengo un script de shell, que es esencialmente un trazador de líneas con algún registro, que estoy tratando de ejecutar esto desde un script de inicio. Estoy usando la daemonfunción dentro de /etc/init.d/functionspara ejecutarlo, ya que Redhat no parece tener start-stop-daemondisponible. Cuando llamo al script de inicio ( /etc/init.d/script start) permanece en primer plano, en lugar de completar y dejar el proceso en ejecución. ¿Cuál es la forma correcta para mí de demonizar este script?

Script a ejecutar:

# 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

guión de inicio:

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

Últimas ~ 20 líneas de ejecución con 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
bshacklett
fuente
Me parece útil que ejecute ese script bash -vx ...y publique las últimas líneas para que podamos ver lo que queda en primer plano.
Hauke ​​Laging
1
No se moleste en utilizar esto correctamente y siga adelante daemon, también hay un paquete RPM . Por cierto, hay muchas herramientas de monitoreo de registros por ahí ( comience aquí ).
Sr_
Hauke, ¿te refieres a usar una primera línea de #!/bin/bash -vx? Intenté hacer esto, pero no produjo el mismo resultado del script de inicio que si ejecuto el script de shell directamente.
bshacklett
@bshacklett puede examinar la función de cualquier script de inicio (cualquier script de shell en realidad) ejecutándolo explícitamente con bash -vx, es decir. bash -vx /etc/init.d/script start.
Sr_
1
@bshacklett Wrt logs, echaría un vistazo más de cerca a logstash . La tienda puede recibir registros directamente desde Log4j, pero el agente logstash también puede monitorear archivos de registro
sr_

Respuestas:

2

Encontré un script en http://www.linuxforums.org/forum/programming-scripting/190279-daemon-etc-init-d-functions-does-not-return-launching-process.html#post897522 que pude para modificar para satisfacer mis necesidades. Rastrea manualmente el PID y crea un archivo PID usando pidof. Terminé teniendo que modificar esto para usarlo, pgrepya que pidofno podía ver el PID de mi script. Después de esa modificación, funcionó bien. * Nota, pgrep parece funcionar solo si el nombre completo del script tiene menos de 15 caracteres

Esto es lo que terminé con:

#!/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 $?
bshacklett
fuente
0

No conozco a Redhat, pero me daemon $prog &parece extraño. Si ya existe una función para demonizar, ¿por qué debería ser necesario (y útil) poner esta función en segundo plano? Por lo tanto, intente sin el &.

Hauke ​​Laging
fuente
44
No esta mal. /etc/init.d/functionsdefine una daemonfunción que espera que su argumento se demonice a sí mismo, solo se ocupa de cosas como cambiar el usuario, establecer ulimits, verificar (¡no crear!) un archivo pid ... El mejor uso de esta daemonfunción es reemplazarlo con libslack'sdaemon ;)
Sr_
Lo siento, el & estaba allí en un momento cuando estaba solucionando problemas. No quise incluirlo en esta publicación.
bshacklett