>>>>>>
<<<<<<
MythBackend has a propensity to crash at inopportune moments (e.g. a couple
hours after you've just left on a week's vacation). Well, nobody's perfect.
Stuff happens. You can't expect to write code that never crashes. But, given
Myth's status as a consumer appliance, you wonder why the Mythbuntu bozos
didn't bother to include this watchdog for MythBackend in the distro. As it
is now, you have to install it yourself.
This section was distilled from:
http://www.mythtv.org/wiki/index.php/Using_pcsk_to_Supervise_mythbackend
Obtain the latest PCSK from http://www.nix.hu/projects/pcsk/. Uncompress and unpack the distro and build it. For example:
mkdir pcsk cd pcsk wget http://downloads.nix.hu/downloads/pcsk/pcsk-0.0.5.tar.bz2 tar xjf pcsk-0.0.5.tar.bz2 cd pcsk-0.0.5 make sudo make install
Create the following script (from Mythbuntu 8.04LTS) in your pcsk directory (see below for a Mythbuntu 9.04 script). I called mine mythtv-backend.pcsk:
#! /bin/sh ### BEGIN INIT INFO # Provides: mythtv-backend # Required-Start: $local_fs $remote_fs $network # Required-Stop: $local_fs # Default-Start: 50 # Default-Stop: S # Short-Description: Start/Stop the MythTV server. ### END INIT INFO # # modified mythtv-backend rc script # V0.22 by EW 6th Jun 2008: # Updated for Mythbuntu 8.04LTS # Removed mythtv-status # v0.21 by DJK 3rd Dec 2007: # Removed -0 option for pcsk # mythbackend seems to catch all signals (even when core # dumping) and still exits 0! so we actually need to restart # it no matter what its exit code was... # v0.2 by DJK 28th Nov 2007: # Added pcsk supervision to restart if it dies # Had to lose NICE for now, sorry. Might be able to use renice # sometime in the future? # Call mythtv-status script for extra details # PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DAEMON=/usr/bin/mythbackend NAME="mythbackend" DESC="MythTV server" # Check that the mythbackend binary exists if ! [ -x "$DAEMON" ] ; then log_end_msg "Could not find $DAEMON binary" exit 1 fi # Check that the pcsk binary exists somewhere in the path (I choose # /usr/local/bin) if ! PCSKBINARY="`which pcsk`" > /dev/null 2>&1; then log_end_msg "Could not find pcsk binary to supervise $NAME. \ Try www.nix.hu/projects/pcsk..." exit 1 fi . /lib/lsb/init-functions set -e prime_firewire() { if [ "$ENABLE_FIREWIRE" = "TRUE" ]; then log_daemon_msg "Priming Firewire " su - $USER -c "/usr/bin/mythprime" log_end_msg $? fi } USER=mythtv USER_HOME=$(grep ^$USER /etc/passwd | awk -F : '{print $6}') RUNDIR=/var/run/mythtv # mythbackend arguments - I've removed --daemon since pcsk will daemonise # it for me ARGS="--logfile /var/log/mythtv/mythbackend.log --pidfile $RUNDIR/$NAME.pid" EXTRA_ARGS="" NICE=0 # The pid and log files for pcsk to use PCSKPIDFILE="$RUNDIR/$NAME-pcsk.pid" PCSKLOGFILE="/var/log/mythtv/mythbackend-pcsk.log" # Command line options for pcsk: # -r: restart the program if it dies # -e: log stderr, if there is any # -o: log stdout, if there is any ## -0: don't restart if the exit code was 0 - not using this at the moment # -w3: wait 3 sec before restart (default in original script) # -i10: increment each wait between restarts by 10s # -c10: restart up to 10 times if the restart is unsuccessful, before giving # up # -m60: restart wasn't successful if the program exits within 60 sec # -p $PIDFILE: use that file for the pid # -l $PCSKLOGFILE: log file to keep track of things - good to set up # logrotate PCSKOPTS="-reo -w3 -i10 -c10 -m60 -p $PCSKPIDFILE -l $PCSKLOGFILE" # Check for alternate options for mythtv-backend if [ -f /etc/default/mythtv-backend ]; then . /etc/default/mythtv-backend fi ARGS="$ARGS $EXTRA_ARGS" PCSKARGS="$PCSKOPTS $DAEMON -- $ARGS" mkdir -p $RUNDIR chown -R $USER $RUNDIR unset DISPLAY unset SESSION_MANAGER #create a symbolic link for mysql.txt so it can't be overwritten mkdir -p $USER_HOME/.mythtv chown -R $USER $USER_HOME/.mythtv if [ ! -e $USER_HOME/.mythtv/mysql.txt ]; then ln -s /etc/mythtv/mysql.txt $USER_HOME/.mythtv/mysql.txt fi case "$1" in start) # Check if pcsk is already supervising this process by checking for # the existance of a pidfile and that it's a currently running process PCSKPID= DAEMONPID= if [ -e "$PCSKPIDFILE" ] ; then read PCSKPID < "$PCSKPIDFILE" if [ -n "$PCSKPID" ] && [ -d "/proc/$PCSKPID" ] ; then # pcsk is running, what about our daemon? if [ -e "$RUNDIR/$NAME.pid" ] ; then read DAEMONPID < "$RUNDIR/$NAME.pid" if [ -n "$DAEMONPID" ] && [ -d "/proc/$DAEMONPID" ] ; then # daemon is running too log_success_msg "pcsk($NAME) (pid $PCSKPID) is already \ running, supervising $NAME (pid $DAEMONPID); \ use restart instead." exit 1 fi # daemon isn't running at the moment (pcsk might be waiting # to respawn it) anyway, take the opportunity to restart # everything now log_success_msg "pcsk($NAME) (pid $PCSKPID) is running but \ $NAME is currently stopped. Restarting now..." $0 restart exit $? fi fi fi prime_firewire log_daemon_msg "Starting $DESC: pcsk($NAME) " # NICE gets ignored because pcsk doesn't support it and start-stop-daemon # would just nice pcsk, not the daemon. # Maybe we could somehow use renice? Later... if ! start-stop-daemon --start --pidfile "$PCSKPIDFILE" \ --chuid $USER --exec "$PCSKBINARY" -- $PCSKARGS ; then log_end_msg "failed (start-stop-daemon exited with code $?)" exit 1 fi log_end_msg $? ;; stop) log_daemon_msg "Stopping $DESC: pcsk($NAME) " start-stop-daemon --stop --oknodo --pidfile "$PCSKPIDFILE" \ --chuid $USER --retry 5 --exec "$PCSKBINARY" -- $PCSKARGS log_end_msg $? [ -e "$PCSKPIDFILE" ] && rm -f "$PCSKPIDFILE" [ -e "$RUNDIR/$NAME.pid" ] && rm -f "$RUNDIR/$NAME.pid" ;; restart) $0 stop sleep 3 $0 start ;; force-reload) log_daemon_msg "force-reload not supported, restarting instead..." $0 restart ;; status) # We have an advantage in this mess that we know what the pidfiles # (and therefore pids) are. Poor-man's status can be had by checking # for the existance of a pidfile and then that it's a currently running # process by looking for that directory in /proc PCSKPID= DAEMONPID= if [ -e "$PCSKPIDFILE" ] ; then read PCSKPID < "$PCSKPIDFILE" if [ -n "$PCSKPID" ] && [ -d "/proc/$PCSKPID" ] ; then echo "pcsk($NAME) (pid $PCSKPID) is running..." else echo "pcsk($NAME) is dead but pid file exists" fi else echo "pcsk($NAME) is stopped" fi if [ -e "$RUNDIR/$NAME.pid" ] ; then read DAEMONPID < "$RUNDIR/$NAME.pid" if [ -n "$DAEMONPID" ] && [ -d "/proc/$DAEMONPID" ] ; then echo "$NAME (pid $DAEMONPID) is running..." else echo "$NAME is dead but pid file exists" fi else echo "$NAME is stopped" fi ;; *) echo "Usage: $0 {start|stop|restart|status|force-reload(unsupported)}" \ >&2 exit 2 ;; esac exit 0
The mythtv-backend script has been updated for Mythbuntu 9.04. Here is an updated version of the script for Mythbuntu 9.04:
#! /bin/sh ### BEGIN INIT INFO # Provides: mythtv-backend # Required-Start: $local_fs $remote_fs $network # Required-Stop: $local_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start/Stop the MythTV server. ### END INIT INFO # # modified mythtv-backend rc script # V0.23 by EW 22th Sep 2009: # Updated for Mythbuntu 9.04 # V0.22 by EW 6th Jun 2008: # Updated for Mythbuntu 8.04LTS # Removed mythtv-status # v0.21 by DJK 3rd Dec 2007: # Removed -0 option for pcsk # mythbackend seems to catch all signals (even when core # dumping) and still exits 0! so we actually need to restart # it no matter what its exit code was... # v0.2 by DJK 28th Nov 2007: # Added pcsk supervision to restart if it dies # Had to lose NICE for now, sorry. Might be able to use renice # sometime in the future? # Call mythtv-status script for extra details # PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DAEMON=/usr/bin/mythbackend NAME="mythbackend" DESC="MythTV server" . /lib/lsb/init-functions # Check that the mythbackend binary exists if ! [ -x "$DAEMON" ] ; then log_failure_msg "Could not find $DAEMON binary" log_end_msg 1 exit 1 fi # Check that the pcsk binary exists somewhere in the path (I choose # /usr/local/bin) if ! PCSKBINARY="`which pcsk`" > /dev/null 2>&1; then log_failure_msg "Could not find pcsk binary to supervise $NAME. \ Try www.nix.hu/projects/pcsk..." log_end_msg 1 exit 1 fi set -e prime_firewire() { if [ "$ENABLE_FIREWIRE" = "TRUE" ]; then log_daemon_msg "Priming Firewire " su - $USER -c "/usr/bin/mythprime" log_end_msg $? fi } USER=mythtv USER_HOME=$(grep ^$USER /etc/passwd | awk -F : '{print $6}') RUNDIR=/var/run/mythtv # mythbackend arguments - I've removed --daemon since pcsk will daemonise # it for me ARGS="--logfile /var/log/mythtv/mythbackend.log --pidfile $RUNDIR/$NAME.pid" EXTRA_ARGS="" NICE=0 # The pid and log files for pcsk to use PCSKPIDFILE="$RUNDIR/$NAME-pcsk.pid" PCSKLOGFILE="/var/log/mythtv/mythbackend-pcsk.log" # Command line options for pcsk: # -r: restart the program if it dies # -e: log stderr, if there is any # -o: log stdout, if there is any ## -0: don't restart if the exit code was 0 - not using this at the moment # -w3: wait 3 sec before restart (default in original script) # -i10: increment each wait between restarts by 10s # -c10: restart up to 10 times if the restart is unsuccessful, before giving # up # -m60: restart wasn't successful if the program exits within 60 sec # -p $PIDFILE: use that file for the pid # -l $PCSKLOGFILE: log file to keep track of things - good to set up # logrotate PCSKOPTS="-reo -w3 -i10 -c10 -m60 -p $PCSKPIDFILE -l $PCSKLOGFILE" # Check for alternate options for mythtv-backend if [ -f /etc/default/mythtv-backend ]; then . /etc/default/mythtv-backend fi ARGS="$ARGS $EXTRA_ARGS" PCSKARGS="$PCSKOPTS $DAEMON -- $ARGS" mkdir -p $RUNDIR chown -R $USER $RUNDIR unset DISPLAY unset SESSION_MANAGER # Check that the MythTV home directory exists. if [ ! -d $USER_HOME ]; then log_failure_msg "MythTV home directory, $USER_HOME does not exist." exit 1 fi #create a symbolic link for mysql.txt so it can't be overwritten mkdir -p $USER_HOME/.mythtv chown -R $USER $USER_HOME/.mythtv if [ ! -e $USER_HOME/.mythtv/mysql.txt ]; then ln -s /etc/mythtv/mysql.txt $USER_HOME/.mythtv/mysql.txt fi #create config.xml for bindings if [ ! -e $USER_HOME/.mythtv/config.xml ]; then ln -s /etc/mythtv/config.xml $USER_HOME/.mythtv/config.xml fi case "$1" in start) # Check if pcsk is already supervising this process by checking for # the existance of a pidfile and that it's a currently running # process PCSKPID= DAEMONPID= if [ -e "$PCSKPIDFILE" ] ; then read PCSKPID < "$PCSKPIDFILE" if [ -n "$PCSKPID" ] && [ -d "/proc/$PCSKPID" ] ; then # pcsk is running, what about our daemon? if [ -e "$RUNDIR/$NAME.pid" ] ; then read DAEMONPID < "$RUNDIR/$NAME.pid" if [ -n "$DAEMONPID" ] && [ -d "/proc/$DAEMONPID" ] ; then # daemon is running too log_success_msg "pcsk($NAME) (pid $PCSKPID) is \ already running, supervising $NAME \ (pid $DAEMONPID); use restart instead." exit 1 fi # daemon isn't running at the moment (pcsk might be waiting # to respawn it). Anyway, take the opportunity to restart # everything now log_success_msg "pcsk($NAME) (pid $PCSKPID) is running \ but $NAME is currently stopped. Restarting now..." $0 restart exit $? fi fi fi prime_firewire log_daemon_msg "Starting $DESC: pcsk($NAME) " # NICE gets ignored because pcsk doesn't support it and # start-stop-daemon would just nice pcsk, not the daemon. # Maybe we could somehow use renice? Later... if ! start-stop-daemon --start --pidfile "$PCSKPIDFILE" --chuid $USER \ --exec "$PCSKBINARY" -- $PCSKARGS ; then log_failure_msg "failed (start-stop-daemon exited with code $?)" log_end_msg 1 exit 1 fi log_end_msg $? ;; stop) log_daemon_msg "Stopping $DESC: pcsk($NAME) " start-stop-daemon --stop --oknodo --pidfile "$PCSKPIDFILE" \ --chuid $USER --retry 5 --exec "$PCSKBINARY" -- $PCSKARGS log_end_msg $? [ -e "$PCSKPIDFILE" ] && rm -f "$PCSKPIDFILE" [ -e "$RUNDIR/$NAME.pid" ] && rm -f "$RUNDIR/$NAME.pid" ;; restart|force-reload) log_daemon_msg "Restarting $DESC: $NAME " $0 stop sleep 3 $0 start log_end_msg $? ;; status) # We have an advantage in this mess that we know what the pidfiles # (and therefore pids) are. Poor-man's status can be had by checking # for the existance of a pidfile and then that it's a currently # running process by looking for that directory in /proc PCSKPID= DAEMONPID= if [ -e "$PCSKPIDFILE" ] ; then read PCSKPID < "$PCSKPIDFILE" if [ -n "$PCSKPID" ] && [ -d "/proc/$PCSKPID" ] ; then echo "pcsk($NAME) (pid $PCSKPID) is running..." else echo "pcsk($NAME) is dead but pid file exists" fi else echo "pcsk($NAME) is stopped" fi if [ -e "$RUNDIR/$NAME.pid" ] ; then read DAEMONPID < "$RUNDIR/$NAME.pid" if [ -n "$DAEMONPID" ] && [ -d "/proc/$DAEMONPID" ] ; then echo "$NAME (pid $DAEMONPID) is running..." else echo "$NAME is dead but pid file exists" fi else echo "$NAME is stopped" fi ;; *) N=/etc/init.d/$NAME echo "Usage: $N {start|stop|restart|force-reload|status}" >&2 exit 2 ;; esac exit 0
Once you've created the script, stop the backend, copy the script to the /etc/init.d directory, rename the original script to get it out of the way and then symlink the new script as the backend startup script:
sudo /etc/init.d/mythtv-backend stop sudo cp mythtv-backend.pcsk /etc/init.d/mythtv-backend.pcsk cd /etc/init.d sudo chmod ugo+x mythtv-backend.pcsk sudo mv mythtv-backend mythtv-backend.orig sudo ln -s mythtv-backend.pcsk mythtv-backend sudo /etc/init.d/mythtv-backend start
Finally, you'll probably want to update the logrotate config file for mythtv-backend (/etc/logrotate.d/mythtv-backend) to rotate the log file created by pcsk too, by adding the following lines to it:
/var/log/mythtv/mythbackend-pcsk.log { daily rotate 7 notifempty copytruncate }