Como adicionar corretamente um daemon personalizado ao init.d?

26

Eu tenho um daemon de servidor de aplicativos proprietário de terceiros que pode ser iniciado e interrompido por algumas linhas de comando. Preciso que esse daemon seja iniciado quando o sistema inicializar e parar corretamente no sistema desligado. Como faço para implementar isso corretamente? É suficiente copiar algum script dentro do /etc/init.d e modificá-lo de acordo?

Ivan
fonte

Respostas:

16

init.d é o sistema antigo e obsoleto para iniciar daemons; Este foi substituído pelo iniciante . O upstart tem a vantagem de ser muito mais fácil de configurar e permite o seqüenciamento adequado da inicialização da tarefa.

Os arquivos de configuração do upstart estão em / etc / init e se o seu daemon não possui pré-requisitos, pode ser tão simples quanto 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

nesse caso, você pode copiar esse arquivo e modificá-lo a seu gosto. Configurações mais complexas são melhor documentadas no site inicial e em outras entradas em / etc / init.

adicionado em resposta ao comentário

Se você usa o upstart ou o init.d, ainda precisará de alguma maneira de determinar quando o Firebird é inicializado corretamente. Infelizmente, o Firebird em si não parece ter uma boa maneira de verificar se está instalado e funcionando . Portanto, a recomendação de colocar o seu programa inicial no /etc/rc.local é certamente a mais fácil, e no Ubuntu - pelo menos - é garantido que será executado o mais tarde possível no processo de inicialização.

msw
fonte
1
Na verdade, meu daemon depende do servidor de banco de dados Firebird, que usa init.d.
Ivan
12

se você não deseja migrar para o UPSTART, mas deseja a abordagem clássica, deve:

NOTA: estou salvando o serviço e o programa com o mesmo nome em diretórios diferentes (mas você pode alterar isso, desde que esteja refletido no seu arquivo de serviço). mude "myscriptname" e "myprogramname" para nomes reais!

  1. salve seu programa que será executado como um serviço em / usr / sbin

    sudo cp myprogramname /usr/sbin/myscriptname

  2. crie um script básico de inicialização (use /etc/init.d/skeleton como referência)

  3. mova esse script para /etc/init.d

    sudo mv /etc/init.d/myscriptname

  4. dê permissão a este script executável (usei 775, mas você pode configurá-lo mais baixo)

    sudo chmod 755 /etc/init.d/myscriptname

  5. vá para /etc/init.d

    cd /etc/init.d

  6. incluir na lista de inicialização com baixa prioridade de inicialização

    sudo update-rc.d myscriptname defaults 97 03

reinicie sua máquina e verifique se o serviço foi iniciado corretamente

sudo ps -A --sort cmd

se o seu serviço não estiver sendo iniciado corretamente, verifique primeiro se ele é executado quando chamado manualmente:

cd /etc/init.d
sudo service myscriptname start

abaixo, incluo um arquivo de serviço de amostra que realmente funciona. compare-o ao serviço de esqueleto para entender o que você precisa configurar. NOTA: isso funciona na implementação LAMP clássica do AWS EC2 da nuvem amazônica Ubuntu 12.04 (também no 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
fonte
1
@jakeDeve-se tempo para reformatar o código "meu". isso significa que você testou e funcionou para você?
gil tony
1
ele trabalhou para mim
Mario S
O iniciante não está morto agora a favor do systemd?
Gillespie
De fato, o iniciante nem está instalado no meu recente Ubuntu. Os scripts de inicialização do SysV nunca morrerão.
Chris Nadovich
8

Faça uma cópia do /etc/init.d/skeleton e edite-a nos locais apropriados para iniciar / parar / reiniciar o serviço. É muito bem comentado, portanto, você poderá criar um script init.d funcionando em pouco tempo.

phuihock
fonte
Isso significa que você também precisa criar links simbólicos no rcX.d. No entanto, uma atualização do Ubuntu apaga todos os seus links simbólicos personalizados.
Robin Hsu
2
  • Adicione seus comandos ao /etc/rc.local
  • Para que seu daemon inicie automaticamente na inicialização do sistema.
karthick87
fonte
1

pleaseruné um script ruby ​​que tenta resolver o problema de criar automaticamente um script init com um único comando. citando sua página:

"Com o pleaserun, você pode gerar os seguintes lançadores / scripts / o que for:

launchd
iniciante
systemd
runit
sysv init "

Ele também detecta qual sistema init está em uso e gera o script de acordo.

Costin Gușă
fonte
não tenho certeza se o pleaserun também faz o log, mas esse outro também possui o log: gist.github.com/naholyr/4275302
Costin Gué