#!/bin/bash # # runvdr extreme - configurable vdr launcher script # # Copyright (C) 2006-2009 Udo Richter # 2013 Manuel Reimer # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html # # The authors can be reached at # # # The project's page is at # http://projects.vdr-developer.org/projects/runvdr-extreme RUNVDR="${0##*/}" RUNVDRCONF="" # Some unix commands being used: PGREP="pgrep" PS="ps" GETOPT="getopt" SLEEP="sleep" CHVT="chvt" DATE="date" # Options summary and conf file entries of runvdr: # # -C # --runvdr-conf=# RUNVDRCONF location of runvdr config file # -- ADDPARAMS Additional parameters to pass to VDR # --pluginsetup-conf=# PLUGINSETUPCONF location of plugin-setup-runvdr.conf # --setupplugin-conf=# SETUPPLUGINCONF location of setup-plugin sysconfig # --vdr=# VDRPRG location and name of the vdr binary # --switchterminal=# SWITCHTERMINAL console terminal to switch to # --xserver=# XSERVER start X server for VDR # --runvdr-pid=# RUNVDRPID location of runvdr.pid file # --dvb-load=# DVBLOAD command to load DVB drivers # --dvb-unload=# DVBUNLOAD command to unload DVB drivers # --dvb-unload-on-exit DVBUNLOADONEXIT do unload DVB drivers on exit # --x-startup=# XSTARTUP command executed after X startup # --x-shutdown=# XSHUTDOWN command executed before X shutdown # --wrapper=# WRAPPER wrapper command for calling vdr # --terminate[=#] TERMINATE Terminate runvdr by pid # --wait[=#] WAIT Wait # seconds for --terminate to finish # --restart[=#] RESTART Send restart signal by pid # --dvb-restart[=#] DVBRESTART Send dvb-restart signal by pid # --term-timeout=# TERMTIMEOUT Timeout for VDR to react on SIGTERM # --kill-timeout=# KILLTIMEOUT Timeout for VDR to react on SIGKILL # --maxrestarts=# MAXRESTARTS Max number of rapid restarts before give-up # --restarttime=# RESTARTTIME Max time for restart to be rapid # --language=# LANGUAGE Locale to set for VDR # --charset-override=# VDR_CHARSET_OVERRIDE Override VDR charset # -V --version VERSION print version information and exit # -h --help HELP print this help and exit # # Supported options of VDR # # -a # --audio # AUDIO send Dolby Digital audio to stdin of command # # --cachedir=# CACHEDIR save cache files in DIR # -c # --config # CONFIGDIR read config files from DIR # -d --daemon DAEMON run in daemon mode # -D # --device # DVBDEVICE use only the given DVB device (NUM = 0, 1, 2...) # --dirnames=# DIRNAMES Changes recording directory name format # -E # --epgfile # EPGFILE write the EPG data into the given FILE. - to disable. # -g # --grab # GRAB write images from the SVDRP command GRAB into the given DIR; # -L # --lib # LIBDIR search for plugins in DIR (default is %s) # --lirc #? LIRC use a LIRC remote control device, attached to PATH # --localedir # LOCALEDIR search for locale files in DIR # -i # --instance # INSTANCE use ID as the id of this VDR instance # -l # --log # LOGLEVEL set log level (default: 3) # -m --mute MUTE mute audio of the primary DVB device at startup # --no-kbd NOKBD don't use the keyboard as an input device # -P # --plugin # PLUGINS load a plugin defined by the given options # -p # --port # SVDRPPORT use PORT for SVDRP # --rcu #? RCU use a remote control device, attached to PATH # -r # --record # RECORDCMD call CMD before and after a recording # --resdir=# RESDIR read resource files from DIR # -s # --shutdown # SHUTDOWN call CMD to shutdown the computer # -t # --terminal # TERMINAL controlling tty # -u # --user # USER run as user USER; only applicable if started as root # --userdump USERDUMP allow coredumps if -u is given (debugging) # --vfat VFAT encode special characters in recording names # -v # --video # VIDEODIR use DIR as video directory # -w # --watchdog # WATCHDOG activate the watchdog timer with a timeout of SEC which $PGREP >/dev/null || { echo missing $PGREP... >&2 ; exit 1 ; } which $PS >/dev/null || { echo missing $PS... >&2 ; exit 1 ; } which $GETOPT >/dev/null || { echo missing $GETOPT... >&2 ; exit 1 ; } which $SLEEP >/dev/null || { echo missing $SLEEP... >&2 ; exit 1 ; } which $CHVT >/dev/null || { echo missing $CHVT... >&2 ; exit 1 ; } which $DATE >/dev/null || { echo missing $DATE... >&2 ; exit 1 ; } function ParseCommandLine_Step1() { # Parse command line, step 1 # Stores pre-processed options in $OPTIONS # evaluates -C, and --runvdr-conf only SHORTOPT="a:c:C:dD:E:g:hi:l:L:mp:P:r:s:t:u:v:Vw:" LONGOPT="runvdr-conf:,pluginsetup-conf:,setupplugin-conf:,vdr:,\ switchterminal:,maxrestarts:,restarttime:,xserver:,\ runvdr-pid:,dvb-load:,dvb-unload:,dvb-unload-on-exit,x-startup:,\ x-shutdown:,language:,charset-override:,wrapper:,\ term-timeout:,kill-timeout:,terminate::,restart::,dvb-restart::,\ wait::,audio:,cachedir:,config:,daemon,device:,dirnames:,epgfile:,grab:,help,lib:,lirc::,\ instance:,log:,localedir:,mute,no-kbd,plugin:,port:,rcu::,record:,resdir:,shutdown:,\ terminal:,user:,userdump,version,vfat,video:,watchdog:" # prepare all optios for later processing OPTIONS=`$GETOPT -o "$SHORTOPT" --long "$LONGOPT" -n "$0" -- "$@"` || exit 1 eval set -- "$OPTIONS" while true ; do case "$1" in -C|--runvdr-conf) RUNVDRCONF="$2"; shift 2;; --pluginsetup-conf) shift 2;; --setupplugin-conf) shift 2;; --vdr) shift 2;; --switchterminal) shift 2;; --xserver) shift 2;; --runvdr-pid) shift 2;; --dvb-load) shift 2;; --dvb-unload) shift 2;; --dvb-unload-on-exit) shift ;; --x-startup) shift 2;; --x-shutdown) shift 2;; --language) shift 2;; --charset-override) shift 2;; --wrapper) shift 2;; --term-timeout) shift 2;; --kill-timeout) shift 2;; --terminate) shift 2;; --wait) shift 2;; --restart) shift 2;; --dvb-restart) shift 2;; --maxrestarts) shift 2;; --restarttime) shift 2;; -h|--help) shift ;; -V|--version) shift ;; -a|--audio) shift 2;; --cachedir) shift 2;; -c|--config) shift 2;; -d|--daemon) shift ;; -D|--device) shift 2;; --dirnames) shift 2;; -E|--epgfile) shift 2;; -g|--grab) shift ;; -i|--instance) shift 2;; -l|--log) shift 2;; -L|--lib) shift 2;; --lirc) shift 2;; --localedir) shift 2;; -m|--mute) shift ;; --no-kbd) shift ;; -p|--port) shift 2;; -P|--plugin) shift 2;; --rcu) shift 2;; -r|--record) shift 2;; --resdir) shift 2;; -s|--shutdown) shift 2;; -t|--terminal) shift 2;; -u|--user) shift 2;; --userdump) shift ;; -v|--video) shift 2;; --vfat) shift ;; -w|--watchdog) shift 2;; --) shift break ;; *) echo "Internal error!" >&2 exit 1 ;; esac ; done } function Clean() { # Clean all config variables ADDPARAM= ADDPARAMS=() PLUGINSETUPCONF= SETUPPLUGINCONF= VDRPRG=vdr SWITCHTERMINAL= XSERVER= RUNVDRPID= DVBLOAD= DVBUNLOAD= DVBUNLOADONEXIT= XSTARTUP= XSHUTDOWN= LANGUAGE= export VDR_CHARSET_OVERRIDE= WRAPPER= TERMTIMEOUT= KILLTIMEOUT= TERMINATE= RESTART= DVBRESTART= MAXRESTARTS=5 RESTARTTIME=10 WAIT=0 HELP= VERSION= AUDIO= CACHEDIR= CONFIGDIR= DAEMON= DVBDEVICE=() DIRNAMES= EPGFILE= GRAB= INSTANCE= LIBDIR= LIRC= LOGLEVEL= LOCALEDIR= MUTE= NOKBD= PLUGINS=() SVDRPPORT= RECORDCMD= RESDIR= RCU= SHUTDOWN= TERMINAL= USER= USERDUMP= VFAT= VIDEODIR= WATCHDOG= } # Helper functions function AddPluginString() { # add $1 as plugin if [ -n "$1" -a -z "${1##-*}" ] ; then local pattern="${1#-}*" local -a plugins1 plugins1=("${PLUGINS[@]}") PLUGINS=() for i in "${plugins1[@]}" ; do [ -n "${i##$pattern}" ] && PLUGINS[${#PLUGINS[*]}]="$i"; done else [ -n "$1" ] && PLUGINS[${#PLUGINS[*]}]="$1"; fi return 0 } function AddPlugin() { # add $* as plugin, do shell quoting local plugin="" while [ $# -gt 0 ] ; do # regexp magic # quote '\' to '\\' local par="$1" par="${par//'\'/\\\\}" # work around bash bug: double quoted '\' par="${par//'\\'/\\\\}" # quote '"' to '\"' par="${par//\"/\\\"}" # check if this splits into words local -a arr=($par) # if yes, wrap in quotes [ ${#arr[*]} -ne 1 ] && par="\"$par\"" # add to plugin string if [ -n "$plugin" ] ; then plugin="$plugin $par" ; else plugin="$par" ; fi # next, please shift done AddPluginString "$plugin" } function AddDevice() { if [ -n "$1" -a -z "${1##-*}" ] ; then local pattern="${1#-}*" local -a devices1 devices1=("${DVBDEVICE[@]}") DVBDEVICE=() for i in "${devices1[@]}" ; do [ -n "${i##$pattern}" ] && DVBDEVICE[${#DVBDEVICE[*]}]="$i"; done else [ -n "$1" ] && DVBDEVICE[${#DVBDEVICE[*]}]="$1"; fi } function AddParams() { # Add to unparsed parameter list for i ; do ADDPARAMS[${#ADDPARAMS[*]}]="$i" done } function INCLUDE() { # include different conf file(s) for file ; do if [ -r "$file" ] ; then . "$file" || exit 1 else echo "runvdr: $file not found." >&2 fi done } function LoadConfFile() { # Load configuration file VDRUSER="" # Old option, supported for compatibility only if [ -z "$RUNVDRCONF" -a -r ~/.$RUNVDR.conf ] ; then RUNVDRCONF=~/.$RUNVDR.conf fi if [ -z "$RUNVDRCONF" -a -r /etc/$RUNVDR.conf ] ; then RUNVDRCONF=/etc/$RUNVDR.conf fi if [ -z "$RUNVDRCONF" -a -r ~/.runvdr.conf ] ; then RUNVDRCONF=~/.runvdr.conf fi if [ -z "$RUNVDRCONF" -a -r /etc/runvdr.conf ] ; then RUNVDRCONF=/etc/runvdr.conf fi if [ -n "$RUNVDRCONF" ] ; then if [ -r "$RUNVDRCONF" ] ; then . "$RUNVDRCONF" || { echo "runvdr: $RUNVDRCONF returned with $?." >&2 ; exit 1 ; } else echo "runvdr: $RUNVDRCONF not found." >&2 fi fi if [ -n "$VDRUSER" ] ; then echo "runvdr: VDRUSER is deprecated. Use USER= instead." [ -n "$USER" ] && USER="$VDRUSER" fi # Transform some defaults, so empty parameters can have a # non-default meaning [ -z "$LIRC" ] && LIRC=0 [ -z "$RCU" ] && RCU=0 [ -z "$TERMINATE" ] && TERMINATE=0 [ -z "$RESTART" ] && RESTART=0 [ -z "$DVBRESTART" ] && DVBRESTART=0 [ -z "$MAXRESTARTS" ] && MAXRESTARTS=5 [ -z "$RESTARTTIME" ] && RESTARTTIME=10 # Compatibility: Map old ADDPARAM to new AddParams [ -n "$ADDPARAM" ] && eval "AddParams $ADDPARAM" return 0 } function ParseCommandLine_Step2() { # Parse command line, step 2 # Process all options in $OPTIONS, override # all options that are set by now eval set -- "$OPTIONS" while true ; do case "$1" in -C|--runvdr-conf) shift 2;; --pluginsetup-conf) PLUGINSETUPCONF="$2"; shift 2;; --setupplugin-conf) SETUPPLUGINCONF="$2"; shift 2;; --vdr) VDRPRG="$2"; shift 2;; --switchterminal) SWITCHTERMINAL="$2"; shift 2;; --xserver) XSERVER="$2"; shift 2;; --runvdr-pid) RUNVDRPID="$2"; shift 2;; --dvb-load) DVBLOAD="$2"; shift 2;; --dvb-unload) DVBUNLOAD="$2"; shift 2;; --dvb-unload-on-exit) DVBUNLOADONEXIT=1; shift ;; --x-startup) XSTARTUP="$2"; shift 2;; --x-shutdown) XSHUTDOWN="$2"; shift 2;; --language) LANGUAGE="$2"; shift 2;; --charset-override) VDR_CHARSET_OVERRIDE="$2"; shift 2;; --wrapper) WRAPPER="$2"; shift 2;; --term-timeout) TERMTIMEOUT="$2"; shift 2;; --kill-timeout) KILLTIMEOUT="$2"; shift 2;; --terminate) TERMINATE="$2"; shift 2;; --wait) WAIT="$2"; shift 2;; --restart) RESTART="$2"; shift 2;; --dvb-restart) DVBRESTART="$2"; shift 2;; --maxrestarts) MAXRESTARTS="$2"; shift 2;; --restarttime) RESTARTTIME="$2"; shift 2;; -h|--help) HELP=1; shift ;; -V|--version) VERSION=1; shift ;; -a|--audio) AUDIO="$2"; shift 2;; --cachedir) CACHEDIR="$2"; shift 2;; -c|--config) CONFIGDIR="$2"; shift 2;; -d|--daemon) DAEMON=1; shift ;; -D|--device) AddDevice "$2"; shift 2;; --dirnames) DIRNAMES="$2"; shift 2;; -E|--epgfile) EPGFILE="$2"; shift 2;; -g|--grab) GRAB="1"; shift ;; -i|--instance) INSTANCE="$2"; shift 2;; -l|--log) LOGLEVEL="$2"; shift 2;; -L|--lib) LIBDIR="$2"; shift 2;; --lirc) LIRC="$2"; shift 2;; --localedir) LOCALEDIR="$2"; shift 2;; -m|--mute) MUTE=1; shift ;; --no-kbd) NOKBD=1; shift ;; -p|--port) SVDRPPORT="$2"; shift 2;; -P|--plugin) AddPluginString "$2"; shift 2;; --rcu) RCU="$2"; shift 2;; -r|--record) RECORDCMD="$2"; shift 2;; --resdir) RESDIR="$2"; shift 2;; -s|--shutdown) SHUTDOWN="$2"; shift 2;; -t|--terminal) TERMINAL="$2"; shift 2;; -u|--user) USER="$2"; shift 2;; --userdump) USERDUMP="$2"; shift ;; -v|--video) VIDEODIR="$2"; shift 2;; --vfat) VFAT=1; shift ;; -w|--watchdog) WATCHDOG="$2"; shift 2;; --) shift break ;; *) echo "Internal error!" >&2 exit 1 ;; esac ; done # Add all remaining options directly to additional params AddParams "$@" return 0 } function OnlineHelp() { cat </dev/null for ((i=0;i<$3;i++)) ; do $PS ${childlist[*]} >/dev/null || { echo terminated. ; return ; } echo -n . $SLEEP 1 done echo echo -n "Sending ${#childlist[*]} processes the KILL signal." kill -KILL ${childlist[*]} 2>/dev/null for ((i=0;i<$4;i++)) ; do $PS ${childlist[*]} >/dev/null || { echo terminated. ; return ; } echo -n . $SLEEP 1 done echo failed. } # Helper functions to handle X server function StartXServer() { XSERVERPID= if [ -n "$XSERVER" ] ; then # X server sends "SIGUSR1" to its parent process, when ready to accept # connections, if the signal is ignored by the child process. # (See man Xserver). ( trap "" USR1 exec $XSERVER ) & XSERVERPID=$! # Wait for X to end or for signal to arrive SIG= wait $XSERVERPID # If anything works as expected, we should have received SIGUSR1. if [ "$SIG" != "USR1" ]; then echo "Xserver startup failed with exit code $?!" >&2 exit 1 fi # Export DISPLAY export DISPLAY=":0" if [[ "$XSERVER" =~ \ (:[0-9.]+) ]]; then DISPLAY="${BASH_REMATCH[1]}" fi # X startup command Do_XSTARTUP fi } function StopXServer() { if [ -n "$XSERVERPID" ] ; then # X shutdown command Do_XSHUTDOWN # Get sure X server is down WaitKill $XSERVERPID ${XSERVER%% *} $TERMTIMEOUT $KILLTIMEOUT fi } # Helper functions for callbacks function Do_DVBLOAD() { if [ -n "$DVBLOAD" ] ; then eval "$DVBLOAD" elif [ "`type -t DVBLOAD`" = "function" ] ; then DVBLOAD fi } function Do_DVBUNLOAD() { if [ -n "$DVBUNLOAD" ] ; then eval "$DVBUNLOAD" elif [ "`type -t DVBUNLOAD`" = "function" ] ; then DVBUNLOAD fi } function Do_XSTARTUP() { if [ -n "$XSTARTUP" ] ; then eval "$XSTARTUP" elif [ "`type -t XSTARTUP`" = "function" ] ; then XSTARTUP fi } function Do_XSHUTDOWN() { # X shutdown command if [ -n "$XSHUTDOWN" ] ; then eval "$XSHUTDOWN" elif [ "`type -t XSHUTDOWN`" = "function" ] ; then XSHUTDOWN fi } #### --------------- #### Main script #### --------------- # Parse command line, step 1 ParseCommandLine_Step1 "$@" || exit 1 # Clean variables Clean # Load and process all configuration LoadConfFile || exit 1 # Process command line ParseCommandLine_Step2 || exit 1 if [ -n "$HELP" ] ; then OnlineHelp exit 0 fi if [ -n "$VERSION" ] ; then echo "runvdr extreme version 0.4.2" exit 0 fi # Get old runvdr pid and move it to options if [ -n "$RUNVDRPID" ] ; then OLDRUNVDRPID="" [ -r "$RUNVDRPID" ] && OLDRUNVDRPID=`<$RUNVDRPID` [ -z "$TERMINATE" ] && TERMINATE="$OLDRUNVDRPID" [ -z "$RESTART" ] && RESTART="$OLDRUNVDRPID" [ -z "$DVBRESTART" ] && DVBRESTART="$OLDRUNVDRPID" fi if [ "$TERMINATE" != "0" ] ; then if [ -n "$TERMINATE" ] ; then echo -n "Terminating runvdr (PID=$TERMINATE)" kill -TERM $TERMINATE while [ -z "$WAIT" ] || [ "$WAIT" -gt 0 ] ; do $PS $TERMINATE >/dev/null || { echo done ; break ; } echo -n "." $SLEEP 1 [ -n "$WAIT" ] && let WAIT=WAIT-1 done echo "" else echo "No runvdr process to terminate." fi exit 0 fi if [ "$RESTART" != "0" ] ; then if [ -n "$RESTART" ] ; then echo -n "Restarting runvdr (PID=$RESTART)..." kill -USR1 $RESTART echo "" else echo "No runvdr process to restart." fi exit 0 fi if [ "$DVBRESTART" != "0" ] ; then if [ -n "$DVBRESTART" ] ; then echo -n "DVB-restarting runvdr (PID=$DVBRESTART)..." kill -USR2 $DVBRESTART echo "" else echo "No runvdr process to dvb-restart." fi exit 0 fi # Build up VDR command BuildCommand || exit 1 # Switch front console [ -n "$SWITCHTERMINAL" ] && $CHVT $SWITCHTERMINAL if [ -n "$LANGUAGE" ] ; then LC_ALL="$LANGUAGE" export LC_ALL fi # Remember PID of this process [ -n "$RUNVDRPID" ] && echo $$ > $RUNVDRPID # Prepare terminal redirection if [ -n "$TERMINAL" ] ; then exec 1>"$TERMINAL" exec 2>"$TERMINAL" fi # Load driver if it hasn't been loaded already: Do_DVBLOAD # Count how often VDR terminated very quickly SHORTRUNTIMES=0 while (true) do echo -n "Starting VDR at " ; $DATE # Trap some signals sent to this script trap "SIG=HUP" SIGHUP trap "SIG=INT" SIGINT trap "SIG=QUIT" SIGQUIT trap "SIG=TERM" SIGTERM trap "SIG=USR1" SIGUSR1 trap "SIG=USR2" SIGUSR2 # Remember start time STARTTIME=`$DATE +%s` echo "${VDRCOMMAND[@]}" # Run X server StartXServer # Run VDR "${VDRCOMMAND[@]}" & # Remember PID of VDR process PID=$! # Wait for VDR to end or signal to arrive SIG= wait $PID # Remember return value of VDR RET=$? # Remember stop time STOPTIME=`$DATE +%s` # Count if time is less than RESTARTTIME seconds, # forget otherwise if [ "$RESTARTTIME" -gt 0 -a $((STOPTIME-STARTTIME)) -le "$RESTARTTIME" ] ; then SHORTRUNTIMES=$((SHORTRUNTIMES+1)) echo "VDR died within $RESTARTTIME seconds, this happened $SHORTRUNTIMES time(s)." else SHORTRUNTIMES=0 fi case "$SIG" in HUP | INT | QUIT | TERM) echo -n "Terminating by request at " ; $DATE # Kill remaining VDR traces WaitKill $PID $VDRPRG $TERMTIMEOUT $KILLTIMEOUT # Stop X server StopXServer # Unload DVB drivers requested? [ -n "$DVBUNLOADONEXIT" ] && Do_DVBUNLOAD # and exit break ;; USR1) echo -n "Restarting VDR by request at " ; $DATE # Kill remaining VDR traces WaitKill $PID $VDRPRG $TERMTIMEOUT $KILLTIMEOUT # Stop X server StopXServer # and loop ;; USR2) echo -n "Restarting VDR and DVB by request at " ; $DATE # Kill remaining VDR traces WaitKill $PID $VDRPRG $TERMTIMEOUT $KILLTIMEOUT # Stop X server StopXServer # reload DVB stuff Do_DVBUNLOAD Do_DVBLOAD ;; *) # Non-signal termination if [ $RET -eq 0 -o $RET -eq 2 ] ; then echo -n "Terminating by error level $RET at " ; $DATE # Kill remaining VDR traces WaitKill $PID $VDRPRG $TERMTIMEOUT $KILLTIMEOUT # Stop X server StopXServer # Unload DVB drivers requested? [ -n "$DVBUNLOADONEXIT" ] && Do_DVBUNLOAD # and exit break fi if [ $SHORTRUNTIMES -gt "$MAXRESTARTS" ] ; then echo -n "Terminating because VDR died $SHORTRUNTIMES times in a row quickly at " ; $DATE # Kill remaining VDR traces WaitKill $PID $VDRPRG $TERMTIMEOUT $KILLTIMEOUT # Stop X server StopXServer # Unload DVB drivers requested? [ -n "$DVBUNLOADONEXIT" ] && Do_DVBUNLOAD # and exit break; fi echo -n "Restarting VDR and DVB by error level $RET at " ; $DATE # Kill remaining VDR traces WaitKill $PID $VDRPRG $TERMTIMEOUT $KILLTIMEOUT # Stop X server StopXServer # reload DVB Do_DVBUNLOAD Do_DVBLOAD # and loop ;; esac # reload configuration Clean LoadConfFile || exit 1 ParseCommandLine_Step2 || exit 1 BuildCommand || exit 1 # Catch remaining in-between signals case "$SIG" in HUP | INT | QUIT | TERM) break ;; esac done # Clean up PID file [ -n "$RUNVDRPID" ] && rm $RUNVDRPID 2>/dev/null