Book HomeBook TitleSearch this book

3.5. Customization and Subprocesses

Some of the variables discussed above are used by commands you may run -- as opposed to the shell itself -- so that they can determine certain aspects of your environment. The majority, however, are not even known outside the shell.

This dichotomy begs an important question: which shell "things" are known outside the shell, and which are only internal? This question is at the heart of many misunderstandings about the shell and shell programming. Before we answer, we'll ask it again in a more precise way: which shell "things" are known to subprocesses? Remember that whenever you enter a command, you are telling the shell to run that command in a subprocess; furthermore, some complex programs may start their own subprocesses.

The answer is actually fairly simple. Subprocesses inherit only environment variables. They are available automatically, without the subprocess having to take any explicit action. All the other "things" -- shell options, aliases, and functions -- must be made explicitly available. The environment file is how you do this. Furthermore, only interactive shells process the environment file. The next two sections describe environment variables and the environment file, respectively.

3.5.1. Environment Variables

By default, only one kind of thing is known to all kinds of subprocesses: a special class of shell variables called environment variables. Some of the built-in variables we have seen are actually environment variables: HISTFILE, HOME, LOGNAME, PATH, PWD, OLDPWD, SHELL, and TERM.

It should be clear why these and other variables need to be known by subprocesses. We have already seen the most obvious example: text editors like vi and Emacs need to know what kind of terminal you are using; TERM is their way of determining this. As another example, most Unix mail programs allow you to edit a message with your favorite text editor. How does mail know which editor to use? The value of EDITOR (or sometimes VISUAL).

Any variable can become an environment variable, and new variables can be created that are environment variables. Environment variables are created with the command:

export varnames

(varnames can be a list of variable names separated by whitespace.) If the names in varnames already exist, then those variables become environment variables. If they don't, the shell creates new variables that are environment variables.

With ksh, you may assign a value and export the variable in one step:

export TMPDIR=/var/tmp

You can also define variables to be in the environment of a particular subprocess (command) only, by preceding the command with the variable assignment, like this:

varname=value command

You can put as many assignments before the command as you want.[46] For example, assume you're using the Emacs editor. You are having problems getting it to work with your terminal, so you're experimenting with different values of TERM. You can do this most easily by entering commands that look like:

[46] There is an obscure option, keyword, that (if turned on) lets you put this type of environment variable definition anywhere on the command line, not just at the beginning.

TERM=trythisone emacs filename

emacs has trythisone defined as its value of TERM, yet the environment variable in your shell keeps whatever value (if any) it had before. This syntax is not very widely used, so we won't see it very often throughout the remainder of this book.

Nevertheless, environment variables are important. Most .profile files include definitions of environment variables; the sample .profile earlier in this chapter contained two such definitions:

EDITOR=/usr/local/bin/emacs
SHELL=/bin/ksh
export EDITOR SHELL

For some reason, the Korn shell doesn't make EDITOR an environment variable by default. This means, among other things, that mail will not know which editor to use when you want to edit a message.[47] Therefore you would have to export it yourself by using the export command in your .profile.

[47] Actually, it will default to the line editor ed. You don't want that, now, do you?

The second line in the previous code is meant for systems that do not have the Korn shell installed as the default shell, i.e., as /bin/sh. Some programs run shells as subprocesses within themselves (e.g., many mail programs and the Emacs editor's shell mode); by convention, they use the SHELL variable to determine which shell to use.

You can find out which variables are environment variables and what their values are by typing export without arguments.

3.5.2. The Environment File

Although environment variables are always known to subprocesses, the shell must be explicitly told which other variables, options, aliases, etc., are to be communicated to subprocesses. The way to do this is to put all such definitions in a special file called the environment file instead of your .profile.

You can call the environment file anything you like, as long as you set the environment variable ENV to the file's name. The usual way to do this is as follows:

  1. Decide which definitions in your .profile you want to propagate to subprocesses. Remove them from .profile and put them in a file you designate as your environment file.

  2. Put a line in your .profile that tells the shell where your environment file is:

    ENV=envfilename
    export ENV
    

    It is important that the value of ENV be exported, so that shell subprocesses are able to find it.

  3. For the changes to take effect immediately, logout and then log back in again.[48] (You can't just use . ~/.profile; the shell does not rerun the $ENV file when the value of ENV changes.)

    [48] This assumes that the Korn shell is defined as your login shell. If it isn't, you should have your system administrator install it as your login shell.

The idea of the environment file comes from the C shell's .cshrc file; thus, many Korn shell users who came from the C shell world call their environment files .kshrc. (The rc suffix for initialization files is practically universal throughout the Unix world. It stands for "run commands" and entered the Unix lexicon by way of MIT's Compatible Time Sharing System (CTSS)).

As a general rule, you should put as few definitions as possible in .profile and as many as possible in your environment file. Because definitions add to rather than take away from an environment, there is little chance that they will cause something in a subprocess not to work properly. (An exception might be name clashes if you go overboard with aliases.)

The only things that really need to be in .profile are commands that aren't definitions but actually run or produce output when you log in. Option and alias definitions should go into the environment file. In fact, there are many Korn shell users who have tiny .profile files, e.g.:

stty stop ^S intr ^C erase ^?
date
from
export ENV=~/.kshrc

(The from command, in some versions of Unix, checks if you have any mail and prints a list of message headers if you do.) Although this is a small .profile, this user's environment file could be huge.

There is an important difference between ksh88 and ksh93. In ksh88, the environment file is always executed. In ksh93, only interactive shells (those not reading from a script, but rather from a terminal) execute the environment file. Thus, it is best that the environment file contain only commands that are useful for interactive use, such as alias and option settings.

Another difference between the two shell versions is that ksh88 only does variable substitution on the value of ENV, while ksh93 does variable, command, and arithmetic substitution on its value. (Command substitution is described in Chapter 4. Arithmetic substitution is described in Chapter 6.)



Library Navigation Links

Copyright © 2003 O'Reilly & Associates. All rights reserved.