Перейти к содержимому
Калькуляторы

Вопрос по start-stop-daemon

Есть сервер со старым Debian, в котором используется не systemd, а LSB.

На нем работает IPTV-стриммер на основе VLC, который запускается в изолированном сеансе screen.

Сейчас хочу написать стартер для VLC, который бы автоматически перезапускался в случае падения VLC.

Написанный стартер под спойлером.

Скрытый текст

#!/bin/sh

### BEGIN INIT INFO
# Provides: vlc-daemon
# Required-Start: $syslog
# Required-Stop: $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: IPTV-streamer (VLC)
### END INIT INFO

SELF=$(readlink -f "$0")
NAME=$(basename "$SELF")
BASE=$(dirname "$SELF")
DESC="IPTV-streamer (VLC)"
VLC=$(which cvlc)
CFG="iptv-cam"
MGT="-I telnet --telnet-port 12345 --telnet-password iptv"
UID="vlcd"
GID="vlcd"
LOG=/var/log/vlcd
PID=/var/run/$NAME.pid

[ -x "$VLC" ] || exit 1
. /lib/init/vars.sh
. /lib/lsb/init-functions

VERBOSE=yes

SSD_START="--start --quiet --chuid=$UID"
SSD_STOP="--stop --quiet"
SSD_FIND="--pidfile $PID --name $NAME"

VLC_ARGS="--quiet --daemon --pidfile $PID $MGT"
VLC_ARGS="$VLC_ARGS --file-logging --logmode text --logfile $LOG/$CFG.log --log-verbose 1"
VLC_ARGS="$VLC_ARGS --ttl=5 --vlm-conf=$BASE/$CFG.conf"

echo >> $LOG/$NAME.log
date +"*** DATE %F, TIME %T, TZ %Z%:z" >> $LOG/$NAME.log
echo "$DESC" >> $LOG/$NAME.log
echo "DIR: $BASE" >> $LOG/$NAME.log
echo "CMD: $0 $*" >> $LOG/$NAME.log
echo "VLC: $VLC" >> $LOG/$NAME.log
echo "ARG: $VLC_ARGS" >> $LOG/$NAME.log

do_start()
{
        if [ ! -e "$LOG/$CFG.log" ]; then
                touch "$LOG/$CFG.log"
                chown $UID:$GID "$LOG/$CFG.log"
                chmod 640 "$LOG/$CFG.log"
        fi
        if [ ! -e "$PID" ]; then
                touch "$PID"
                chown $UID:$GID "$PID"
                chmod 644 "$PID"
        fi
        start-stop-daemon $SSD_START $SSD_FIND --exec $VLC --test > /dev/null \
                || return 1
        start-stop-daemon $SSD_START $SSD_FIND --exec $VLC -- $VLC_ARGS >> $LOG/$NAME.log 2>&1 \
                || return 2
}

do_stop()
{
        start-stop-daemon $SSD_STOP --retry=TERM/30/KILL/5 $SSD_FIND
        RETVAL="$?"
        [ "$RETVAL" = 2 ] && return 2
        start-stop-daemon $SSD_STOP --oknodo --retry=0/30/KILL/5 --exec $VLC
        [ "$?" = 2 ] && return 2
        rm -f $PID
        return "$RETVAL"
}

do_reload() {
        start-stop-daemon $SSD_STOP --signal 1 $SSD_FIND
        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
                ;;
        restart)
                log_daemon_msg "Restarting $DESC" "$NAME"
                do_stop
                case "$?" in
                  0|1)
                        sleep 5
                        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
                        ;;
                  *)
                        log_end_msg 1
                        ;;
                esac
                ;;
        reload)
                echo "reload"
                #del media
                #load $CFG.conf
                ;;
        status)
                status_of_proc -p $PID "$VLC" "$NAME" && exit 0 || exit $?
                ;;
        stats)
                echo "stats"
                ;;
        *)
                echo "Usage: ${NAME} {start|stop|restart|reload|status|stats}"
                exit 1
                ;;
esac

:

 

VLC в режиме сервиса стартует, IPTV транслирует.

Но почему-то не останавливается.

Процедура остановки такая:

do_stop()
{
        start-stop-daemon $SSD_STOP --retry=TERM/30/KILL/5 $SSD_FIND
        RETVAL="$?"
        [ "$RETVAL" = 2 ] && return 2
        start-stop-daemon $SSD_STOP --oknodo --retry=0/30/KILL/5 --exec $VLC
        [ "$?" = 2 ] && return 2
        rm -f $PID
        return "$RETVAL"
}

При выполнении остановки pid-файл удаляется (то есть start-stop-daemon возвращает 0), но процесс продолжает работать.

Я что-то не доделал? Или причина в том, что имя демона и имя исполняемого файла у меня не совпадает?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

 Каким sigusr процесс прибиваете ? -9 ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Никаким.

Если прибивать вручную, то работают и 15, и 9.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

1 час назад, alibek сказал:

Никаким.

Если прибивать вручную, то работают и 15, и 9.

 В древних версиях неоднократно встречал, что пид-файлы не соответствуют демону, или не туда пишутся. Поэтому грепал ps, авкашил пид и килял. Слава догу, во freebsd появился killall  с именем процесса. Для начала у демона уточните, куда он пид пишет, и соответствует ли сей пид из файла реальному пиду из ps.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Все соответствует.

Если перед удалением pid-файла выполнить kill $(cat $PID) , то процесс завершается.

Вопрос в том, почему start-stop-daemon этого не делает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Может через monit проще запилить?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

 Возможно вопрос детский, из серии руками работает а из крона нет ? path не установлен правильно, и утили просто не находятся.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Дело не в path, тогда бы утилита просто не выполнялась.

Она же выполняется, но процесс продолжает работать.

 

Сейчас я процедуру остановки дополнил "костылями":

do_stop()
{
        start-stop-daemon $SSD_STOP --retry=TERM/30/KILL/5 $SSD_FIND
        RETVAL="$?"
        [ "$RETVAL" = 2 ] && return 2
        start-stop-daemon $SSD_STOP --oknodo --retry=0/30/KILL/5 --exec $VLC
        [ "$?" = 2 ] && return 2
        kill $(cat $PID) > /dev/null 2>&1
        sleep 5
        kill -KILL $(cat $PID) > /dev/null 2>&1
        rm -f $PID
        return "$RETVAL"
}

В таком виде процесс убивается.

Но не понятно, почему start-stop-daemon этого не выполняет, у него ведь тоже TERM и KILL указаны.

 

7 часов назад, murano сказал:

Может через monit проще запилить?

Мониторинг много чем можно организовать, но вначале нужно скрипт-стартер довести до рабочего состояния, чтобы он корректно запускал/останавливал сервис.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

И всё же, из консоли оно работает, с --pidfile и --name? start-stop-daemon проверяет соответствие pid и process name.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Да, хорошая мысль, я что-то не сообразил проверить.

# start-stop-daemon --stop --verbose --pidfile /var/run/vlc-daemon.pid --name vlc-daemon --retry=TERM/30/KILL/5
No vlc-daemon found running; none killed.

# start-stop-daemon --status --verbose --pidfile /var/run/vlc-daemon.pid --name vlc-daemon && echo ok || echo fail $?
fail 1

# start-stop-daemon --status --verbose --pidfile /var/run/vlc-daemon.pid  && echo ok || echo fail $?
ok

То есть, хоть я и задавал при запуске --name vlc-daemon, он его все равно не находит.

Если убрать --name и оставить только --pidfile, то все работает.

 

Текущий стартер под спойлером.

Скрытый текст

#!/bin/sh

### BEGIN INIT INFO
# Provides: vlc-daemon
# Required-Start: $syslog
# Required-Stop: $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: IPTV-streamer (VLC)
### END INIT INFO

PATH=/sbin:/usr/sbin:/bin:/usr/bin
SELF=$(readlink -f "$0")
NAME=$(basename "$SELF")
BASE=$(dirname "$SELF")
DESC="IPTV-streamer (VLC)"
VLC=$(which cvlc)
CFG="ipcam-cam"
MGT="-I telnet --telnet-port 12345 --telnet-password iptv"
UID="vlcd"
GID="vlcd"
LOG=/var/log/vlcd
PID=/var/run/$NAME.pid

[ -x "$VLC" ] || exit 1
. /lib/init/vars.sh
. /lib/lsb/init-functions

VERBOSE=yes

SSD_START="--start --quiet --chuid=$UID --name $NAME"
SSD_STOP="--stop --quiet"
SSD_FIND="--pidfile $PID"

VLC_ARGS="--quiet --daemon --pidfile $PID $MGT"
VLC_ARGS="$VLC_ARGS --file-logging --logmode text --logfile $LOG/$CFG.log --log-verbose 0"
VLC_ARGS="$VLC_ARGS --ttl=5 --vlm-conf=$BASE/$CFG.conf"

echo >> $LOG/$NAME.log
date +"*** DATE %F, TIME %T, TZ %Z%:z" >> $LOG/$NAME.log
echo "$DESC" >> $LOG/$NAME.log
echo "DIR: $BASE" >> $LOG/$NAME.log
echo "CMD: $0 $*" >> $LOG/$NAME.log
echo "VLC: $VLC" >> $LOG/$NAME.log
echo "ARG: $VLC_ARGS" >> $LOG/$NAME.log

do_start()
{
        if [ ! -e "$LOG/$CFG.log" ]; then
                touch "$LOG/$CFG.log"
                chown $UID:$GID "$LOG/$CFG.log"
                chmod 640 "$LOG/$CFG.log"
        fi
        if [ ! -e "$PID" ]; then
                touch "$PID"
                chown $UID:$GID "$PID"
                chmod 644 "$PID"
        fi
        start-stop-daemon $SSD_START $SSD_FIND --exec $VLC --test > /dev/null \
                || return 1
        start-stop-daemon $SSD_START $SSD_FIND --exec $VLC -- $VLC_ARGS >> $LOG/$NAME.log 2>&1 \
                || return 2
}

do_stop()
{
        start-stop-daemon $SSD_STOP --retry=TERM/30/KILL/5 $SSD_FIND
        RETVAL="$?"
        [ "$RETVAL" = 2 ] && return 2
        start-stop-daemon $SSD_STOP --oknodo --retry=0/30/KILL/5 --exec $VLC
        [ "$?" = 2 ] && return 2
        rm -f $PID
        return "$RETVAL"
}

do_reload() {
        start-stop-daemon $SSD_STOP --signal 1 $SSD_FIND
        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
                ;;
        restart)
                log_daemon_msg "Restarting $DESC" "$NAME"
                do_stop
                case "$?" in
                  0|1)
                        sleep 5
                        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
                        ;;
                  *)
                        log_end_msg 1
                        ;;
                esac
                ;;
        reload)
                echo "reload"
                #del media
                #load $BASE/$CFG.conf
                ;;
        status)
                status_of_proc -p $PID "$VLC" "$NAME" && exit 0 || exit $?
                ;;
        stats)
                echo "stats"
                ;;
        *)
                echo "Usage: ${NAME} {start|stop|restart|reload|status|stats}"
                exit 1
                ;;
esac

:

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Безопаснее не убирать проверку совсем, а исправить значение --name.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Если бы еще знать, какое name он ищет.

Я полагал, что ищется тот name, который был указан при запуске сервиса (и это имя отличается от имени исполняемого файла).

Более того, если там должно быть имя процесса, то я его в общем случае могу не знать — например я запускаю cvlc, однако в списке процессов вижу vlc.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

3 часа назад, alibek сказал:

Более того, если там должно быть имя процесса, то я его в общем случае могу не знать — например я запускаю cvlc, однако в списке процессов вижу vlc.

 Ps -axw | grep -i vlc. Иногда по ps процессы показываются как задача с путем запуска

 вот во free10

22346  -  S         0:04.30 /usr/local/sbin/httpd

или

 3443  0- S       102:49.69 ./ts3server

 

  Тимспик иногда умирает и падает, мониторю падение примерно так

 

RESULT1=`/bin/ps -ax |/usr/bin/grep ts3server |/usr/bin/grep -v grep |/usr/bin/wc -l`
if [ "$RESULT1" = "       1" ]
/bin/echo "TS Ok $RESULT1"

else
/bin/echo "TS Down Restarted =$RESULT1= loss"

// тут рестарт

fi

 

 С пидом заморачиваться тут не стал, есть в списке процессов строчка - живой, нету - сдох.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Я бы написал что-то типа:

 

RESULT1=`/bin/ps -axc | /usr/bin/grep -c ts3server"

 

:)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

1 час назад, vop сказал:

Я бы написал что-то типа:

 

RESULT1=`/bin/ps -axc | /usr/bin/grep -c ts3server"

 

:)

Ага. И получить почти всегда истину. Грепа-то самого кто убирать будет? :-)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

 Да ладно вам костыли обсуждать :) Накостылено давно, минут за 10, работает да и буй с ним. Почему пидфайл не стал использовать - он просто остается при умершем процессе. Ну и синтаксис ключей утилей - он бывает довольно разный, использовал более-менее стандартные.

 

 Ну и вдогонку, если пидфайл есть, то ps $(cat $PID) выдаст имя процесса, если он есть конечно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

On 5/18/2019 at 9:09 PM, snvoronkov said:

Ага. И получить почти всегда истину. Грепа-то самого кто убирать будет? :-)

Вот там в команде ps есть пуковка це. Внимание вопрос - а нахрена она там нужна? :)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

2 часа назад, vop сказал:

Вот там в команде ps есть пуковка це. Внимание вопрос - а нахрена она там нужна? :)

А действительно? Прикольно.

Век живи, блин, век учись. :-) Причем нашел и в BSD, и в POSIX.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

По итогам недели могу сказать, что скрипт по запуску/перезапуску VLC отрабатывает отлично.

Под спойлером выкладываю скрипты, может кому пригодится.

 

Скрипт-стартер (для LSB или systemd):

Скрытый текст

#!/bin/sh

### BEGIN INIT INFO
# Provides: vlc-daemon
# Required-Start: $syslog
# Required-Stop: $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: IPTV-streamer (VLC)
### END INIT INFO

PATH=/sbin:/usr/sbin:/bin:/usr/bin
SELF=$(readlink -f "$0")
NAME=$(basename "$SELF")
BASE=$(dirname "$SELF")
DESC="IPTV-streamer (VLC)"
VLC=$(which cvlc)
CFG="iptv-cam"
MGT="-I telnet --telnet-port 12345 --telnet-password iptv"
UID="vlcd"
GID="vlcd"
LOG=/var/log/vlcd
PID=/var/run/$NAME.pid

[ -x "$VLC" ] || exit 1
. /lib/init/vars.sh
. /lib/lsb/init-functions

VERBOSE=yes

SSD_START="--start --quiet --chuid=$UID --name $NAME"
SSD_STOP="--stop --quiet"
SSD_FIND="--pidfile $PID"

VLC_ARGS="--quiet --daemon --pidfile $PID $MGT"
VLC_ARGS="$VLC_ARGS --file-logging --logmode text --logfile $LOG/$CFG.log --log-verbose 0"
VLC_ARGS="$VLC_ARGS --ttl=5 --vlm-conf=$BASE/$CFG.conf"

echo >> $LOG/$NAME.log
date +"*** DATE %F, TIME %T, TZ %Z%:z" >> $LOG/$NAME.log
echo "$DESC" >> $LOG/$NAME.log
echo "DIR: $BASE" >> $LOG/$NAME.log
echo "CMD: $0 $*" >> $LOG/$NAME.log
echo "VLC: $VLC" >> $LOG/$NAME.log
echo "ARG: $VLC_ARGS" >> $LOG/$NAME.log

do_start()
{
        if [ ! -e "$LOG/$CFG.log" ]; then
                touch "$LOG/$CFG.log"
                chown $UID:$GID "$LOG/$CFG.log"
                chmod 640 "$LOG/$CFG.log"
        fi
        if [ ! -e "$PID" ]; then
                touch "$PID"
                chown $UID:$GID "$PID"
                chmod 644 "$PID"
        fi
        start-stop-daemon $SSD_START $SSD_FIND --exec $VLC --test > /dev/null \
                || return 1
        start-stop-daemon $SSD_START $SSD_FIND --exec $VLC -- $VLC_ARGS >> $LOG/$NAME.log 2>&1 \
                || return 2
}

do_stop()
{
        start-stop-daemon $SSD_STOP --retry=TERM/30/KILL/5 $SSD_FIND
        RETVAL="$?"
        [ "$RETVAL" = 2 ] && return 2
        start-stop-daemon $SSD_STOP --oknodo --retry=0/30/KILL/5 --exec $VLC
        [ "$?" = 2 ] && return 2
        #kill -KILL $(cat $PID) > /dev/null 2>&1 && sleep 2
        rm -f $PID
        return "$RETVAL"
}

do_reload() {
        start-stop-daemon $SSD_STOP --signal 1 $SSD_FIND
        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
                ;;
        restart)
                log_daemon_msg "Restarting $DESC" "$NAME"
                do_stop
                case "$?" in
                  0|1)
                        sleep 5
                        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
                        ;;
                  *)
                        log_end_msg 1
                        ;;
                esac
                ;;
        reload)
                echo "reload"
                #del media
                #load $BASE/$CFG.conf
                ;;
        status)
                status_of_proc -p $PID "$VLC" "$NAME" && exit 0 || exit $?
                ;;
        stats)
                echo "stats"
                ;;
        *)
                echo "Usage: ${NAME} {start|stop|restart|reload|status|stats}"
                exit 1
                ;;
esac

:

 

 

Скрипт-перезапускалка (добавляется в cron):

Скрытый текст

#!/bin/sh

PIDFILE=/var/run/vlc-daemon.pid
LOGFILE=/var/log/vlcd/iptv-cam.log

[ ! -e "$PIDFILE" ] && exit 0

LEN=$(stat --printf="%s" $LOGFILE)
PID=$(cat $PIDFILE)
CPU=$(ps p $PID -o pcpu=)
MEM=$(ps p $PID -o pmem=)

if [ -z "$MEM" ]; then
        echo
        echo "*** `date +'%F %T'`: process not found (pid $PID), restarting"
        echo
        /etc/init.d/vlc-daemon restart
        exit 1
fi

MEM=`echo $MEM | awk '{print int(10*$1)}'`
if [ "$MEM" -gt 150 ]; then
        echo
        echo "*** `date +'%F %T'`: high memory usage $(($MEM/10))%, restarting"
        echo
        /etc/init.d/vlc-daemon restart
        exit 1
fi

LEN=`echo $LEN | awk '{print int($1/1024/1024)}'`
if [ "$LEN" -gt 20 ]; then
        echo
        echo "*** `date +'%F %T'`: truncate log-file (size $LEN MB)"
        echo
        #truncate --size 0 $LOGFILE
        tail -n 200 $LOGFILE | tee $LOGFILE > /dev/null
        exit 0
fi

 

Скрипт проверяет краш VLC (отсутствие процесса) или утечки памяти и перезапускает основной скрипт.

 

Из мистического — почему-то все краши и глюки VLC случаются ночью, обычно в период с 2 до 3 часов.

В светлое время суток работает как часы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

13 минут назад, alibek сказал:

Скрипт проверяет краш VLC (отсутствие процесса) или утечки памяти и перезапускает основной скрипт.

Что только люди не сделают чтобы monit не ставить. :-)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Гость
Ответить в тему...

×   Вставлено в виде отформатированного текста.   Вставить в виде обычного текста

  Разрешено не более 75 смайлов.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.