Team LiB
Previous Section Next Section

Hack 73. Don't Let Elvis Leave the Building

Keep a program running in the background by automatically restarting it whenever it exits.

Some programs behave contrary to our wishes and exit prematurely, either because they are designed to do so, or because they are flaky and prone to crashing. This hack provides a neat trick to restart such programs automatically every time they exit.

The xcompmgr program that provides drop shadows and other special effects for Xorg is still a work in progress, and it often exits unexpectedly. With a simple script, you can automatically restart it every time it exits. First, log in as root, fire up your favorite editor, and create the following script, naming it /usr/local/bin/keep-xcompmgr-running:

#!/bin/bash
# start up xcompmanager with drop shadows and fade effects
instances=`ps ax | grep "xcompmgr -cCfF" | grep -v grep | wc -l`
if [ $instances == 0 ]; then
while true; do xcompmgr -cCfF -l 0 -t 0 -r 5 -o .6 ; done
else
exit 1
fi

The first thing the script does is check to see if the command is already running. If so, the script exits. Perhaps you forgot you already started this script, or perhaps you started the command manually. In either case, you don't want to start two instances, and this portion of the script prevents that.

How to Ignore grep

Many people use the expression ps ax to see which processes are running, and then pipe the command through a grep command (a search utility) to see if a certain program is in the list. A common problem often occurs when you use a command such as the following in a script to see if xcompmgr is already running:

ps ax | grep xcompmgr

The problem is that even if xcompmgr is not running, the command might return a resultthe grep command itself. The grep command finds the word "xcompmgr" in the process list, because it put the word there:

22833 pts/1    R+     0:00 grep xcompmgr

One way to prevent this is to pipe the results through a second grep command. This time, you pipe it through the command grep -v grep. The -v switch tells grep to ignore lines that include the word "grep."

This is how the following line uses the technique to make sure xcompmgr is not running:

instances=`ps ax | grep "xcompmgr -cCfF" | grep -v grep | wc -l`

First, it generates a process list and pipes it through grep to find lines that contain the string xcompmgr -cCfF. If xcompmgr -cCfF is running, this command might return two lines. One line will show the xcompmgr process running, and the second line will show the grep command that is looking for this program. Then those lines are piped through grep again, this time eliminating lines that contain the word "grep." Finally, it pipes the results through wc -l, which is a command that counts lines of text. If one line is left over after grep removes itself from the list, xcompmgr -cCfF must be running. If no lines are left over after the grep command is removed from the list, you know xcompmgr -cCfF is not running.

You might also be wondering why the script looks for xcompmgr -cCfF rather than something simpler such as xcompmgr. I confess that it's force of habit. Suppose you were looking to see if the xset program is running. If we look for the word "xset" it might find the xsetpointer program, because the xset string appears in that program, too. The script would get the mistaken idea that xset is running, because it found a program with a name that contains the xset string. To avoid this, I have developed the habit of finding ways to make the search string as unique as possible.


Notice that the xcompmgr command is not followed with an ampersand. That would launch xcompmgr in the background and return control to the script. Then the script would proceed to try to launch more instances of xcompmgr over and over again. Trust me. That's a bad thing.

Now save your work and make this script executable with this command:

# chmod +x /usr/local/bin/keep-xcompmgr-running

The script is a simple infinite loop. But it doesn't just start new instances of xcompmgr over and over again. The xcompmgr program does not return control to the script unless it fails, so this script will get to the point where it launches the xcompmgr command and its arguments, and then stop running. If xcompmgr encounters a bug that causes it to exit unexpectedly, control returns automatically to the script, and the loop continues by starting xcompmgr all over again. Then the script stops running until xcompmgr fails again. (See the sidebar, How to Ignore grep.)

9.5.1. Putting the Respawn Trick to Work

One great place to use this trick is in a .xinitrc startup script (or any other method of starting up an application automatically when you run a window manager or graphical desktop). The following .xinitrc script will work, but if xcompmgr crashes, it will stay crashed:

xcompmgr -cCfF -l 0 -t 0 -r 5 -o .6 &
exec /usr/bin/fluxbox

If you instead start up the script that keeps xcompmgr running, it will restart every time it crashes:

/usr/local/bin/keep-xcompmgr-running &
exec /usr/bin/fluxbox

    Team LiB
    Previous Section Next Section