Библиотека сайта rus-linux.net
We've looked in turn at system and user run-control files, at environment variables, and at command-line arguments. Observe the progression from least easily changed to most easily changed. There is a strong convention that well-behaved Unix programs that use more than one of these places should look at them in the order given, allowing later settings to override earlier ones (there are specific exceptions, such as command-line options that specify where a dotfile should be found).
In particular, environment settings usually override dotfile
settings, but can be overridden by command-line options. It is good
practice to provide a command-line option like the -e
of
make(1)
that can override environment settings or declarations in run-control files;
that way the program can be scripted with well-defined behavior
regardless of the way the run-control files look or environment
variables are set.
Which of these places you choose to look at depends on how much persistent configuration state your program needs to keep around between invocations. Programs designed mainly to be used in a batch mode (as generators or filters in pipelines, for example) are usually completely configured with command-line options. Good examples of this pattern include ls(1), grep(1) and sort(1). At the other extreme, large programs with complicated interactive behavior may rely entirely on run-control files and environment variables, and normal use involves few command-line options or none at all. Most X window managers are a good example of this pattern.
(Unix has the capability for the same file to have multiple names or ‘links’. At startup time, every program has available to it the filename through which it was called. One other way to signal to a program that has several modes of operation which one it should come up in is to give it a link for each mode, have it find out which link it was called through, and change its behavior accordingly. But this technique is generally considered unclean and seldom used.)
Let's look at a couple of programs that gather configuration data from all three places. It will be instructive to consider why, for each given piece of configuration data, it is collected as it is.
Case Study: fetchmail
The fetchmail program uses only two
environment variables, USER
and
HOME
. These variables are in the predefined set
initialized by the system; many programs use them.
The value of HOME
is used to find the dotfile
.fetchmailrc
, which contains configuration
information in a fairly elaborate syntax obeying the shell-like
lexical rules described above. This is appropriate because, once it
has been initially set up, Fetchmail's
configuration will change only infrequently.
There is neither an /etc/fetchmailrc
nor
any other systemwide file specific to fetchmail. Normally such files
hold configuration that's not specific to an individual user.
fetchmail does use a small set of properties with this kind of scope
— specifically, the name of the local postmaster, and a few
switches and values describing the local mail transport setup (such as
the port number of the local SMTP listener). In practice, however,
these are seldom changed from their compiled-in default values. When
they are changed, they tend to be modified in user-specific
ways. Thus, there has been no demand for a systemwide fetchmail
run-control file.
Fetchmail can retrieve host/login/password triples from a
.netrc
file. Thus, it gets authenticator
information in the least surprising way.
Fetchmail has an elaborate set of command-line options, which
nearly but do not entirely replicate what the
.fetchmailrc
can express. The set was not
originally large, but grew over time as new constructs were added to
the .fetchmailrc
minilanguage and parallel
command-line options for them were added more or less
reflexively.
The intent of supporting all these options was to make
fetchmail easier to script by allowing
users to override bits of its run control from the command line. But
it turns out that outside of a few options like
--fetchall
and --verbose
there is
little demand for this — and none that can't be satisfied with a
shellscript that creates a temporary run-control file on the fly and
then feeds it to fetchmail using the
-f
option.
Thus, most of the command-line options are never used, and in retrospect including them was probably a mistake; they bulk up the fetchmail code a bit without accomplishing anything very useful.
There is a lesson here; had I thought carefully enough about fetchmail's usage pattern and been a little less ad-hoc about adding features, the extra complexity might have been avoided.
The X windowing system is the engine that supports bitmapped displays on Unix machines. Unix applications running through a client machine with a bitmapped display get their input events through X and send screen-painting requests to it. Confusingly, X ‘servers’ actually run on the client machine — they exist to serve requests to interact with the client machine's display device. The applications sending those requests to the X server are called ‘X clients’, even though they may be running on a server machine. And no, there is no way to explain this inverted terminology that is not confusing.
X servers have a forbiddingly complex interface to their environment. This is not surprising, as they have to deal with a wide range of complex hardware and user preferences. The environment queries common to all X servers, documented on the X(1) and Xserver(1) pages, therefore make a useful example for study. The implementation we examine here is XFree86, the X implementation used under Linux and several other open-source Unixes.
At startup, the XFree86 server examines a systemwide run-control file; the exact pathname varies between X builds on different platforms, but the basename is XF86Config. The XF86Config file has a shell-like syntax as described above. Example═10.2 is a sample section of an XF86Config file.
Example═10.2.═X configuration example.
# The 16-color VGA server Section "Screen" Driver "vga16" Device "Generic VGA" Monitor "LCD Panel 1024x768" Subsection "Display" Modes "640x480" "800x600" ViewPort 0 0 EndSubsection EndSection
The XF86Config file describes the host machine's display hardware (graphics card, monitor), keyboard, and pointing device (mouse/trackball/glidepad). It's appropriate for this information to live in a systemwide run-control file, because it applies to all users of the machine.
Once X has acquired its hardware configuration from the run
control file, it uses the value of the environment variable
HOME
to find two dotfiles in the calling user's home
directory. These files are .Xdefaults
and
.xinitrc
.[105]
The .Xdefaults
file specifies per-user,
application-specific resources relevant to X (trivial examples of
these might include font and foreground/background colors for a
terminal emulator). The phrase ‘relevant to X’ indicates a
design problem, however. Collecting all these resource declarations
in one place is convenient for inspecting and editing them, but it is
not always clear what should be declared in
.Xdefaults
and what belongs in an
application-specific dotfile. The .xinitrc
file
specifies the commands that should be run to initialize the user's X
desktop just after server startup. These programs will almost always
include a window or session manager.
X servers have a large set of command-line options. Some of
these, such as the -fp
(font path) option, override
the XF86Config. Some are intended to help track server bugs, such as
the -audit
option; if these are used at all, they are
likely to vary quite frequently between test runs and are therefore
poor candidates to be included in a run-control file. A very important
option is the one that sets the server's display number. Multiple
servers may run on a host provided each has a unique display number,
but all instances share the same run-control file(s); thus, the
display number cannot be derived solely from those files.