What both user and system environment variables have in common
is that it would be annoying to have to replicate the information they
contain in a large number of application run-control files, and
extremely annoying to have to change that information everywhere when
your preference changes. Typically, the user sets these variables in
his or her shell session startup file.
A value varies across several contexts that share
dotfiles, or a parent needs to pass information to multiple child
processes.
Some pieces of start-up information are expected
to vary across several contexts in which the calling user would share
common run-control files and dotfiles. For a system-level example,
consider several shell sessions open through terminal emulator windows
on an X desktop. They will all see the same dotfiles, but might have
different values of COLUMNS, LINES, and
TERM. (Old-school shell programming used this method
extensively; makefiles still do.)
A value varies too often for dotfiles, but doesn't
change on every startup.
A user-defined environment
variable may (for example) be used to pass a file system or Internet
location that is the root of a tree of files that the program should
play with. The CVS version-control system interprets the variable
CVSROOT this way, for example. Several newsreader
clients that fetch news from servers using the NNTP protocol interpret
the variable NNTPSERVER as the location of the server
to query.
A process-unique override needs to be expressed in a
way that doesn't require the command-line invocation to be
changed.
A user-defined environment variable can be useful
for situations in which, for whatever reason, it would be inconvenient to
have to change an application dotfile or supply command-line options
(perhaps it is expected that the application will normally be used
inside a shell wrapper or within a makefile). A particularly
important context for this sort of use is debugging. Under Linux, for
example, manipulating the variable LD_LIBRARY_PATH
associated with the ld(1) linking loader enables you to change where
libraries are loaded from — perhaps to pick up versions that do
buffer-overflow checking or profiling.
In general, a user-defined environment variable can be an
effective design choice when the value changes often enough to make
editing a dotfile each time inconvenient, but not necessarily every
time (so always setting the location with a command-line option
would also be inconvenient). Such variables should typically be
evaluated
after
a local dotfile and be permitted
to override settings in it.
There is one traditional Unix design pattern that we do not
recommend for new programs. Sometimes, user-set environment variables
are used as a lightweight substitute for expressing a program
preference in a run-control file. The venerable
nethack(1)
dungeon-crawling game, for example, reads a
NETHACKOPTIONS environment variable for user
preferences. This is an old-school technique; modern practice would
lean toward parsing them from a .nethack or
.nethackrc run-control file.
The problem with the older style is that it makes tracking where
your preference information lives more difficult than it would be if
you knew the program had a run-control file under your home directory.
Environment variables can be set anywhere in several different shell
run-control files — under Linux these are likely to include
.profile, .bash_profile, and
.bashrc at least. These files are cluttered and
fragile things, so as the code overhead of having an option-parser has
come to seem less significant preference information has tended to
migrate out of environment variables into dotfiles.
[an error occurred while processing this directive]