X Window System Administration

An introduction to X structure, configuration and customization.
Starting the X Server

There are a few different ways to get the X server started. One of the first methods found by many new users is the startx command, which is actually a shell script wrapper for the xinit program. Using startx with no arguments should be enough to start up an X session; however, unless you have set the DefaultColorDepth as described above, you will probably get only 8 bit-planes. If you want better colors, you will need to add some arguments, like this:

startx -- -bpp 16

This starts X with 16 bit-planes. The first two dashes cause the -bpp 16 to be passed as arguments to the X server, rather than the xinit program. If you get tired of entering the whole command each time, you can create a file named .xserverrc in your home directory and put in it the command to start the X server, like this:

exec X -bpp 16 :0
See the xinit(1) manual page for details.

When X starts, it will switch to the first available virtual screen and use that for the display. Most Linux systems come with the first six virtual screens assigned as virtual consoles, so the user can switch among them by pressing the alt key and a function key (f1-f6) at the same time. To get to one of those from the X display, it is necessary to add the ctrl key, i.e., use ctrl-alt-f1 to get from X to the first virtual console. Then, to return to the X session, press ctrl-alt-f7. If your system doesn't have six virtual consoles enabled, you will have to use a different function key.

Now, if we can have six (or more) virtual consoles, why not have more than one X session? This is done by providing startx with more information. The X server needs to know which virtual screen to use and what to name the display.

For example, to start a 24-bit display on virtual screen 8, type:

startx -- :1 -bpp 24 vt8

and to start an 8-bit display on virtual screen 9, type:

startx -- :2 -bpp 8 vt9
The :1 and :2 are the names that X uses to refer to the displays. The full format for the name is host:N.M, where host is the host name of the system, N is the number of the display on that system, and M is the number of the screen (in multi-headed displays using more than one monitor).

The designation :0 is simply shorthand for the first display on the local system, localhost:0.0. The names :1 and :2 refer to the second and third displays. To switch among them, simply use the ctrl-alt-fn combination.

To see how these work, start up the :1 and :2 displays as shown above, and switch to your first display (:0) using ctrl-alt-f7. Then from a virtual terminal (e.g., xterm, rxvt), run the command

xeyes -display :1

The xeyes program will run (you won't get another shell prompt), but it is not visible on the screen. Now switch to the second display (ctrl-alt-f8) and you will see it. When xeyes exits, you will get another prompt in your shell session on :0.

Many X programs support the -display option to specify the display to use. Note that the environment variable DISPLAY is set to the default display. If you run the command echo $DISPLAY from a virtual terminal in each display, you can see how it is set differently on each one.

When xinit starts up, it starts the X server and then looks for a file called .xinitrc in the user's home directory, which is a shell script that xinit runs. That file usually contains, as a minimum, lines like:

xterm &
exec fvwm

which start an xterm terminal emulator, then it replaces the xinit process with the FVWM window manager. In turn, fvwm looks for its startup file called ~/.fvwmrc. A default for this file can be found in the /etc/X11/fvwm directory. Notice that the xterm process starts running without a window manager. A window manager is not a required part of an X session, but you will probably want to have one.


Using startx is easy, but if you use X a lot you will probably want to log into it directly without the complication of having to log into a text console first. Direct logins to X are handled using XDM. The files in /etc/X11/xdm are used to define a configuration, and then the simple command xdm starts X with an xlogin screen to allow someone to enter their user name and password. Like startx, the xdm command can be entered from a command prompt (as superuser). This is good for testing, but xdm is actually meant to be run automatically during the boot sequence—more on that later. Typing ls to get a listing of my /etc/X11/xdm directory outputs:

GiveConsole Xresources.0 Xsession.0 Xsetup_2
TakeConsole Xservers Xsetup_0 authdir
Xaccess Xservers.0 Xsetup_0.0 chooser
Xresources Xsession Xsetup_1 xdm-config

The key file among these is xdm-config, which is the default configuration file for xdm. The xdm-config file defines the basic configuration, including which files to look in for further setup information. The contents of xdm-config look like Listing 2. Note that the names of other files used by XDM are defined here, so it is possible to use different file names or put the files in other directories. The defaults work fine, but be aware that on other UNIX systems, or even different Linux distributions, files may be in a different location. In any case, you can familiarize yourself with the system's configuration by looking at the xdm-config file.

The information in xdm-config is specified using X resources, which is a bit like setting values of data structure fields in a programming language.

The first line of the file sets DisplayManager.errorLogFile, which is where xdm writes its error messages. If xdm is not starting properly, take a look at the error file. You will probably find some useful messages there. On older Red Hat systems and other UNIX systems, the file was placed in /etc/X11/xdm, but in more recent versions (e.g., Red Hat 5.1), it is in /var/log/xdm-error.log. This is in accordance with the Linux File System Hierarchy Standard (FSSTND).

DisplayManager.pidFile (/var/run/xdm.pid) is a file to which xdm writes its process ID. This can be handy if you are adding customizations and you want to restart X to check if they work. Type the command:

kill -TERM `cat /var/run/xdm.pid`

to kill the xdm process before restarting it. Actually, I prefer the command:

killall -TERM xdm
which does the same thing. A variation is to replace the TERM (terminate) signal with HUP (hangup); this does not shut down any running X sessions, but does restart xdm with the new configuration (used for any new sessions that are started). If you are doing your X administration from within an X session, you may want to use that method to avoid discontinuities in your GUI services.

The file pointed to by DisplayManager.servers (Xservers) is used by xdm to start the X server processes. It contains information that tells xdm how to start each X server process. For example, the line

:0 local /usr/X11R6/bin/X -bpp 16 vt7 :0

in my Xservers file will start display :0 on the local system using the command and arguments as provided. To start more than one display, simply add lines to the Xservers file in this same format. If the Xservers file contains these lines:

:0 local /usr/X11R6/bin/X -bpp 16 vt7 :0
:1 local /usr/X11R6/bin/X -bpp 24 vt8 :1
:2 local /usr/X11R6/bin/X -bpp 8 vt9 :2
three displays will start up when xdm is run—a 16-bit display on virtual terminal 7, a 24-bit display on vt8 and 8-bit on vt9. The -bpp 16 option is redundant, since I've defined DefaultColorDepth to be 16 in my XF86Config file.

Notice the asterisk in the last few lines of xdm-config. This mechanism is called “loose binding” and is a wild card character used to match all possible field names. The field names in this case are the names of the displays. Display :0 is referred to as DisplayManager._0. (It is _0 for display :0, _1 for display :1 and so on.) The underscore is used instead of the colon because in a resource, the colon is a separator between the resource name and its setting. An asterisk means the same file is used for all of the displays, but when the display is specified explicitly (called “tight binding”), the file is used just for that display. Of course, it would be possible to use only tight bindings and specify the same file each time, but the loose binding method is easier.

After the X server starts and before the xlogin program is run, xdm looks in the file defined by the DisplayManager._0.setup resource (Xsetup_0). This is a shell script containing arbitrary commands, so it has a great deal of versatility. I like to put a more pleasing background behind the xlogin window than the default black and white pattern, so I might use a command like this:

/usr/X11/bin/xsetroot -solid darkcyan

to make the background (root window) a solid color. To make things more interesting, the lines:

/usr/X11/bin/xloadimage -onroot \
tile the background with an image of my own design. Be sure the xloadimage program is on your system before doing this.

Again, a warning about security. The program(s) run out of Xsetup._* files may have their keyboard and mouse inputs disabled, but if they do not exit before the user successfully logs in, they will continue to run with superuser (root) permissions. For example, if the line

/usr/X11/bin/rxvt &

were in the Xsetup_0 file, the user who logs in on display :0 is granted a superuser shell, which is not a desired condition. This is an obvious example, but others may not be as obvious, so be careful.

Around Christmas, it might seem cute (and harmless) to put

/usr/X11/bin/xsnow &

into the Xsetup file to make snow appear to fall while the computer is waiting for a login; however, since it will be running with the user ID of root, the user will not have permission to kill the process after login. Also, many people will get tired of seeing snow falling in the background of their X sessions after awhile. Fortunately, there is a way to make the xsnow process exit before the user's login session begins. First, add a line that saves the process ID of xsnow immediately after the one that starts it, like this:

/usr/X11/bin/xsnow &
echo $! >/var/run/xlogin_xsnow.pid
After the user is authenticated by xlogin and before his X session starts, xdm runs the shell script named in the DisplayManager._0.startup resource (GiveConsole). This is normally used to change the ownership of /dev/console to the user, so that error messages directed to the console can be displayed in the X session, using xterm or rxvt with the -C option, or with xconsole. However, you can add whatever you want to the script. For example, the following lines force xsnow to exit:
kill -9 `cat /var/run/xlogin_xsnow.pid`
rm -f /var/run/xlogin_xsnow.pid
Now, here's an exercise for you. Many sites want the ability to shut down the system directly from the xlogin screen without requiring the user to log in or su with the root password. With your favorite text editor, create a Tcl/Tk script named xlogin_buttons that contains the lines shown in Listing 3, and make it executable with the command:
chmod +x xlogin_buttons

Now follow the above xsnow example to modify your Xsetup_0 and GiveButtons scripts to use the Tcl/Tk script instead of xsnow. I put the script in /etc/X11/xdm and put these lines in my Xsetup_0 script:

/etc/X11/xdm/xlogin_buttons &
echo $! >/var/run/xlogin_buttons_0.pid

and these two lines in my GiveConsole script:

kill -9 `cat /var/run/xlogin_buttons_0.pid`
rm -f /var/run/xlogin_buttons_0.pid
Be sure to check that the Xsetup_0 and GiveConsole files are defined in the xdm-config file.

Along with the DisplayManager._0.startup resource is DisplayManager._0.reset (TakeConsole), invoked after the X session ends and before xdm resets the X server prior to the next login. Normally, this simply changes the ownership of /dev/console back to root, but you can add customizations there too.