¿Cómo agregar correctamente un demonio personalizado a init.d?

26

Tengo un demonio de servidor de aplicaciones propietario de terceros que se puede iniciar y detener mediante un par de líneas de comando. Necesito que este demonio se inicie cuando el sistema se inicie y se detenga correctamente al apagar el sistema. ¿Cómo implemento esto correctamente? ¿Es suficiente copiar algún script dentro de /etc/init.d y modificarlo en consecuencia?

Ivan
fuente

Respuestas:

16

init.d es el viejo y obsoleto sistema para iniciar demonios; Esto ha sido suplantado por advenedizo . Upstart tiene la ventaja de ser mucho más fácil de configurar y permite una secuencia adecuada de la inicialización de la tarea.

Los archivos de configuración para el programa de inicio viven en / etc / init y si su daemon no tiene requisitos previos, puede ser tan simple como tty1.conf:

# tty1 - getty
#
# This service maintains a getty on tty1 from the point the system is
# started until it is shut down again.

start on stopped rc RUNLEVEL=[2345]
stop on runlevel [!2345]

respawn
exec /sbin/getty -8 38400 tty1

en cuyo caso puede copiar ese archivo y modificarlo al gusto. Las configuraciones más complejas se documentan mejor en el sitio inicial y en otras entradas en / etc / init.

agregado en respuesta al comentario

Ya sea que use upstart o init.d, aún necesitará alguna forma de determinar cuándo Firebird se inicializa correctamente. Desafortunadamente, Firebird en sí mismo no parece tener una buena forma de verificar que esté instalado y funcionando . Por lo tanto, la recomendación de pegar el inicio de su programa en /etc/rc.local es ciertamente la más fácil, y en Ubuntu, al menos, se garantiza que se ejecute lo más tarde posible en el proceso de arranque.

msw
fuente
1
En realidad, mi demonio depende del servidor de base de datos Firebird, que usa init.d.
Ivan
12

Si no desea migrar a UPSTART, pero desea el enfoque clásico, debe:

NOTA: estoy guardando el servicio y el programa con el mismo nombre en diferentes directorios (pero puede cambiar esto, siempre que se refleje en su archivo de servicio). ¡cambie "myscriptname" y "myprogramname" a nombres reales!

  1. guarde su programa que se ejecutará como un servicio en / usr / sbin

    sudo cp myprogramname /usr/sbin/myscriptname

  2. crear un script de inicio básico (use /etc/init.d/skeleton como referencia)

  3. mueva este script a /etc/init.d

    sudo mv /etc/init.d/myscriptname

  4. otorgue a este script permiso de ejecución (utilicé 775, pero puede configurarlo más bajo)

    sudo chmod 755 /etc/init.d/myscriptname

  5. goto /etc/init.d

    cd /etc/init.d

  6. incluir en la lista de inicio con baja prioridad de inicio

    sudo update-rc.d myscriptname defaults 97 03

reinicie su máquina y verifique si el servicio se inició correctamente

sudo ps -A --sort cmd

Si su servicio no se inicia correctamente, primero debe verificar si se ejecuta cuando lo llama a mano:

cd /etc/init.d
sudo service myscriptname start

a continuación incluyo un archivo de servicio de muestra que realmente funciona. compárelo con el servicio de esqueleto para comprender lo que necesita configurar. NOTA: esto funciona en la implementación de Ubuntu 12.04 amazon cloud AWS EC2 classic LAMP (también en Kubuntu 15.10).

#! /bin/sh
### BEGIN INIT INFO
# Provides:          
# Required-Start:    $remote_fs
# Required-Stop:     $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Sample_GT02 daemon startup script
# Description:       Sample Server for GT02 class 
### END INIT INFO

# Author: Tony Gil 
#

# Do NOT "set -e"

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="Sample Daemon"
NAME=sampleserver_gt02
DAEMON=/usr/sbin/$NAME
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
CHUID=root

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions

#
# Function that starts the daemon/service
#
do_start()
{
   # Return
   #   0 if daemon has been started
   #   1 if daemon was already running
   #   2 if daemon could not be started
   start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
      || return 1
   start-stop-daemon --start --quiet --chuid $CHUID --pidfile $PIDFILE --exec $DAEMON -- \
      $DAEMON_ARGS \
      || return 2
}

#
# Function that stops the daemon/service
#
do_stop()
{
   # Return
   #   0 if daemon has been stopped
   #   1 if daemon was already stopped
   #   2 if daemon could not be stopped
   #   other if a failure occurred
   start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
   RETVAL="$?"
   [ "$RETVAL" = 2 ] && return 2
   # Wait for children to finish too if this is a daemon that forks
   # and if the daemon is only ever run from this initscript.
   # If the above conditions are not satisfied then add some other code
   # that waits for the process to drop all resources that could be
   # needed by services started subsequently.  A last resort is to
   # sleep for some time.
   start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
   [ "$?" = 2 ] && return 2
   # Many daemons don't delete their pidfiles when they exit.
   rm -f $PIDFILE
   return "$RETVAL"
}

#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
   #
   # If the daemon can reload its configuration without
   # restarting (for example, when it is sent a SIGHUP),
   # then implement that here.
   #
   start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
   return 0
}

case "$1" in
  start)
   [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
   do_start
   case "$?" in
      0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
      2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
   esac
   ;;
  stop)
   [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
   do_stop
   case "$?" in
      0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
      2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
   esac
   ;;
  #reload|force-reload)
   #
   # If do_reload() is not implemented then leave this commented out
   # and leave 'force-reload' as an alias for 'restart'.
   #
   #log_daemon_msg "Reloading $DESC" "$NAME"
   #do_reload
   #log_end_msg $?
   #;;
  restart|force-reload)
   #
   # If the "reload" option is implemented then remove the
   # 'force-reload' alias
   #
   log_daemon_msg "Restarting $DESC" "$NAME"
   do_stop
   case "$?" in
     0|1)
      do_start
      case "$?" in
         0) log_end_msg 0 ;;
         1) log_end_msg 1 ;; # Old process is still running
         *) log_end_msg 1 ;; # Failed to start
      esac
      ;;
     *)
        # Failed to stop
      log_end_msg 1
      ;;
   esac
   ;;
  *)
   #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
   echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
   exit 3
   ;;
esac

:
Tony Gil
fuente
1
@jakeGould realmente te tomaste el tiempo para reformatear "mi" código ¿eso significa que lo probaste y funcionó para ti?
tony gil
1
funcionó para mí
Mario S
¿Acaso no está muerto ahora a favor de systemd?
Gillespie
De hecho, el advenedizo ni siquiera está instalado en mi Ubuntu reciente. Los scripts de inicio de SysV nunca morirán.
Chris Nadovich
8

Haga una copia de /etc/init.d/skeleton y edítela en los lugares apropiados para iniciar / detener / reiniciar su servicio. Está muy bien comentado, por lo que debería poder crear un script init.d que funcione en poco tiempo.

phuihock
fuente
Significa que también necesita crear enlaces simbólicos en rcX.d. Sin embargo, una actualización de Ubuntu eliminará todos sus enlaces simbólicos personalizados.
Robin Hsu
2
  • Agregue sus comandos a /etc/rc.local
  • Para que tu demonio se inicie automáticamente al iniciar el sistema.
karthick87
fuente
1

pleaserunes un script de ruby ​​que intenta resolver el problema de crear automáticamente un script de inicio con un solo comando. citando de su página:

"Con pleaserun, puede generar los siguientes lanzadores / scripts / lo que sea:

"startd
upstart
systemd
runit
sysv init"

También detecta qué sistema de inicio está en uso, por lo que genera el script en consecuencia.

Costin Gușă
fuente
no estoy seguro si pleaserun también registra, pero este otro también tiene registros: gist.github.com/naholyr/4275302
Costin Gușă