Problema de script do Debian de 7 a 8 Init

2

Eu movi recentemente um serviço caseiro que eu rodava em uma máquina virtual (Debian 7.8) para um computador físico (Debian 8.5) e depois da mudança, meu script de inicialização parou de funcionar. Eu entendo que houve algumas mudanças importantes no processo init, etc. entre Wheezy e Jessie, mas até onde eu sei, as mudanças ainda devem ser compatíveis com o meu script de inicialização. Eu tenho certeza que eu 'LSBizei' o script de acordo com as instruções no Debian Wiki e fiquei bem perto do antigo exemplo de esqueleto .

Eu dei muita comoção, tentando descobrir o que estava acontecendo e tenho certeza de que o script (geralmente?) está falhando - ou pelo menos parando - enquanto procura as funções em /lib/lsb/init-functions . Eu não tenho ideia de por que isso aconteceria.

Depois de chegar a essa conclusão, reduzi o script de inicialização para uma versão mais curta (bem desajeitada) que não usa as funções init; ele apenas bifurca um processo bash em um shell secundário e ficará órfão. Isso parece funcionar um pouco melhor, mas ainda tem problemas ocasionais com a nova configuração de serviços. Estou menos interessado em consertar essa solução de fita adesiva e fita adesiva, pois estou descobrindo por que meu script de inicialização mais padronizado é mal-comportado.

Alguma idéia?

Aqui está meu script de inicialização antigo:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          myd
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Initscript for myService daemon
### END INIT INFO

# 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="myService daemon"
NAME=myd
DAEMON=/home/uname/myService/bin/$NAME
DAEMON_ARGS=""
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME

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

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

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /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 \
        --background \
        --pidfile $PIDFILE \
        --make-pidfile \
        --user uname \
        --chuid uname \
                --startas /bin/bash \
        --test \
        -- -c "exec $DAEMON >> /.myd/var/init.log 2>&1" \
        || return 1
    start-stop-daemon --start --quiet \
        --background \
        --pidfile $PIDFILE \
        --make-pidfile \
        --user uname \
        --chuid uname \
                --startas /bin/bash \
        -- -c "exec $DAEMON >> /home/uname/.myd/var/init.log 2>&1" \
                || return 2
    # Add code here, if necessary, that waits for the process to be ready
    # to handle requests from services started subsequently which depend
    # on this one.  As a last resort, sleep for some time.
    return 0
}

#
# 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)
    log_daemon_msg "Starting $DESC" "$NAME"
    do_start
    case "$?" in
        0|1) log_end_msg 0
        ;;
        2) log_end_msg 1
        ;;
    esac
    ;;
  stop)
    log_daemon_msg "Stopping $DESC" "$NAME"
    do_stop
    case "$?" in
        0|1) log_end_msg 0
        ;;
        2) log_end_msg 1
        ;;
    esac
    ;;
  status)
    status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
    ;;
  #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|status|restart|force-reload}" >&2
    exit 3
    ;;
esac

:

E meu novo script (desajeitado) que (principalmente) funciona:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          myd
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Initscript for myService daemon
### END INIT INFO

# 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="myService daemon"
NAME=myd
DAEMON=/home/uname/myService/bin/$NAME
DAEMON_ARGS=""
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME

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

#
# Function that starts the daemon/service
#
do_start()
{
    (
        runuser -l uname "$DAEMON" >/dev/null 2>&1 &
        echo "$!" > "$PIDFILE"
    )
    return 0
}

#
# Function that stops the daemon/service
#
do_stop()
{
    PID="$(cat $PIDFILE)"
    kill "$PID" >/dev/null 2>&1

    #Give myd 5 seconds for an orderly shutdown
    for i in $(seq 1 5); do
        sleep 1
        if [ ! kill -0 "$PID" >/dev/null 2>&1 ]; then
            rm "$PIDFILE"
            return 0;
        fi
    done

    #No more playing nice: KILL THE DAEMON
    if [ kill -0 "$PID" >/dev/null 2>&1 ]; then
        echo "Orderly shutdown failed, sending kill signal"
        kill -9 "$PID" >/dev/null 2>&1
    fi

    #Give myd 5 more seconds then fail
    for i in $(seq 1 5); do
        sleep 1
        if [ ! kill -0 "$PID" >/dev/null 2>&1 ]; then
            rm "$PIDFILE"
            return 0;
        fi
    done

    #FAILED
    echo "Failed to kill $DESC $NAME"
    return 1
}

case "$1" in
  start)
    echo "Starting $DESC $NAME" >&2
    do_start
    ;;
  stop)
    echo "Stopping $DESC $NAME" >&2
    do_stop
    ;;
  restart|force-reload)
    #
    # If the "reload" option is implemented then remove the
    # 'force-reload' alias
    #
    echo "Restarting $DESC $NAME" >&2
    do_stop
    do_start
    ;;
  *)
    #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
    echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
    exit 3
    ;;
esac

:

Como um aparte, depois de muito googling e head-scratching, eu ainda não estou muito ciente do novo sistema de boot de dependência, etc. Alguém pode me apontar na direção de alguma documentação (atual) para essas coisas, então eu posso auto educar um pouco melhor? Eu odeio estar no escuro sobre os sistemas com os quais estou trabalhando.

Obrigado!

    
por Justin Frahm 04.09.2016 / 21:35

1 resposta

2

Você provavelmente deve considerar a conversão para uma Unidade Systemd nativa, pois seu script init é bastante típico, e você poderia, por exemplo, remover completamente o código de parada e deixar o mecanismo padrão do systemd funcionar para você, já que você tem um PIDFILE o daemon está rodando e sabe como matá-lo (veja man systemd.kill ).

O systemd tem uma grande curva de aprendizado, mas você pode começar com este blog . convertendo para systemd pelo próprio homem, Lennart Poettering.

Normalmente, seu script de inicialização deve continuar funcionando, devido à compatibilidade interna do systemd. Consulte man systemd-sysv-generator e procure o wrapper do arquivo systemd Unit para seu script myd em /run/systemd/generator.late/myd.service .

Verifique o status e o log do seu script com

sudo systemctl status myd

e pare e inicie da mesma forma. Observe a pegadinha que descrevi em esta resposta , onde dar uma segunda partida para algo que o systemd pensa já está iniciado não terá efeito.

Veja este wiki para converter o System V ou scripts upstart como o seu para Unidades systemd nativas.

    
por 05.09.2016 / 15:24