Jump to content

Recommended Posts

Posted

Есть сервер со старым 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), но процесс продолжает работать.

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

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

Никаким.

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

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

Posted

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

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

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

Posted

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

Posted

Дело не в 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 проще запилить?

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

Posted

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

# 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

:

 

 

Posted

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

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

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

Posted
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

 

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

 

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

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

 

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

 

:)

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

Posted

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

 

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

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

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

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

 

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

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

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

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

  • 2 weeks later...
Posted

По итогам недели могу сказать, что скрипт по запуску/перезапуску 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 часов.

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

Posted
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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...
На сайте используются файлы cookie и сервисы аналитики для корректной работы форума и улучшения качества обслуживания. Продолжая использовать сайт, вы соглашаетесь с использованием файлов cookie и с Политикой конфиденциальности.