alibek Posted May 16, 2019 · Report post Есть сервер со старым 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), но процесс продолжает работать. Я что-то не доделал? Или причина в том, что имя демона и имя исполняемого файла у меня не совпадает? Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
YuryD Posted May 16, 2019 · Report post Каким sigusr процесс прибиваете ? -9 ? Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
alibek Posted May 16, 2019 · Report post Никаким. Если прибивать вручную, то работают и 15, и 9. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
YuryD Posted May 16, 2019 · Report post 1 час назад, alibek сказал: Никаким. Если прибивать вручную, то работают и 15, и 9. В древних версиях неоднократно встречал, что пид-файлы не соответствуют демону, или не туда пишутся. Поэтому грепал ps, авкашил пид и килял. Слава догу, во freebsd появился killall с именем процесса. Для начала у демона уточните, куда он пид пишет, и соответствует ли сей пид из файла реальному пиду из ps. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
alibek Posted May 16, 2019 · Report post Все соответствует. Если перед удалением pid-файла выполнить kill $(cat $PID) , то процесс завершается. Вопрос в том, почему start-stop-daemon этого не делает. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
murano Posted May 16, 2019 · Report post Может через monit проще запилить? Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
YuryD Posted May 17, 2019 · Report post Возможно вопрос детский, из серии руками работает а из крона нет ? path не установлен правильно, и утили просто не находятся. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
alibek Posted May 17, 2019 · Report post Дело не в 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 проще запилить? Мониторинг много чем можно организовать, но вначале нужно скрипт-стартер довести до рабочего состояния, чтобы он корректно запускал/останавливал сервис. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
ixi Posted May 17, 2019 · Report post И всё же, из консоли оно работает, с --pidfile и --name? start-stop-daemon проверяет соответствие pid и process name. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
alibek Posted May 17, 2019 · Report post Да, хорошая мысль, я что-то не сообразил проверить. # 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 : Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
ixi Posted May 17, 2019 · Report post Безопаснее не убирать проверку совсем, а исправить значение --name. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
alibek Posted May 17, 2019 · Report post Если бы еще знать, какое name он ищет. Я полагал, что ищется тот name, который был указан при запуске сервиса (и это имя отличается от имени исполняемого файла). Более того, если там должно быть имя процесса, то я его в общем случае могу не знать — например я запускаю cvlc, однако в списке процессов вижу vlc. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
YuryD Posted May 17, 2019 · Report post 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 С пидом заморачиваться тут не стал, есть в списке процессов строчка - живой, нету - сдох. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
vop Posted May 18, 2019 · Report post Я бы написал что-то типа: RESULT1=`/bin/ps -axc | /usr/bin/grep -c ts3server" :) Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
snvoronkov Posted May 18, 2019 · Report post 1 час назад, vop сказал: Я бы написал что-то типа: RESULT1=`/bin/ps -axc | /usr/bin/grep -c ts3server" :) Ага. И получить почти всегда истину. Грепа-то самого кто убирать будет? :-) Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
YuryD Posted May 19, 2019 · Report post Да ладно вам костыли обсуждать :) Накостылено давно, минут за 10, работает да и буй с ним. Почему пидфайл не стал использовать - он просто остается при умершем процессе. Ну и синтаксис ключей утилей - он бывает довольно разный, использовал более-менее стандартные. Ну и вдогонку, если пидфайл есть, то ps $(cat $PID) выдаст имя процесса, если он есть конечно. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
vop Posted May 20, 2019 · Report post On 5/18/2019 at 9:09 PM, snvoronkov said: Ага. И получить почти всегда истину. Грепа-то самого кто убирать будет? :-) Вот там в команде ps есть пуковка це. Внимание вопрос - а нахрена она там нужна? :) Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
snvoronkov Posted May 20, 2019 · Report post 2 часа назад, vop сказал: Вот там в команде ps есть пуковка це. Внимание вопрос - а нахрена она там нужна? :) А действительно? Прикольно. Век живи, блин, век учись. :-) Причем нашел и в BSD, и в POSIX. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
alibek Posted May 28, 2019 · Report post По итогам недели могу сказать, что скрипт по запуску/перезапуску 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 часов. В светлое время суток работает как часы. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
snvoronkov Posted May 28, 2019 · Report post 13 минут назад, alibek сказал: Скрипт проверяет краш VLC (отсутствие процесса) или утечки памяти и перезапускает основной скрипт. Что только люди не сделают чтобы monit не ставить. :-) Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
alibek Posted May 28, 2019 · Report post monit делает то же самое. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...