## 3.3. Shell Setup Files -- Which, Where, and Why

To understand setup files, you need to understand that a shell can act like a login shell or a nonlogin shell (Section 3.4). There are different setup files for nonlogin and login shells.

When you log in to a Unix system -- but not under a window system -- the login program starts a shell for you. The login program sets a special flag (Section 3.19) to tell a shell that it's a login shell. If the shell doesn't have that flag set, it won't act like a login shell. Opening a new window in a window system may or may not set the "login shell" flag -- that depends on the configuration. (For example, the command xterm -ls starts a login shell in an xterm window (Section 24.20); xterm +ls starts a nonlogin shell.) When you connect to a system with programs like ftp and scp, that usually starts a nonlogin shell. And a subshell (Section 24.4) is never a login shell (unless you set a command-line option to force a login shell, like `bash -l`).

How can you tell whether your shell is a login shell? The answer is "it depends." When you first log in to a system, you want a login shell that sets things like the terminal type (Section 5.2, Section 5.3). Other shells on the same terminal should be nonlogin shells -- to avoid redoing those one-time-only setup commands. Different shells have their own methods for handling first-time shell invocations versus later invocations, and that's what the rest of this article is about.

Parenthesis operators (Section 43.7) don't read any setup file. Instead, they start another instance of your current shell. Parentheses are called "subshell operators," but the subshell they start doesn't print a prompt and usually has a short lifetime.

Next, let's look at the setup files -- login and nonlogin -- for the major shells. I recommend that you read about all of them. Then experiment with your shell's setup files until you get things working the way you want them.

System-wide setup
  Your login(1) command probably sets some environment variables ( Section 35.3) like HOME, PATH, SHELL, TERM, MAIL, and LOGNAME or USER; check its manual page. Your system may set some environment variables or other parameters that apply to all shells or to all shells of a particular type (all bash shells, zsh shells, etc.). All of these will be passed through the environment, from parent process to child process (Section 35.4), to all of your shells, login and nonlogin.

  Once login or your window system starts your individual shell, it may also read its own system-wide setup files. These files, if any, will be read before your personal setup files. Check your shell's manual page and the /etc directory for files like csh.login, bashrc, zshrc, and so on. On Red Hat systems, for example, there is a directory named /etc/profile.d containing package-specific C and Bash shell config files that are sourced (read into the current shell) on startup of a shell. On Mac OS X, when you use Terminal (Section 3.2), your shell (which is tcsh by default) reads /private/etc/csh.cshrc, as well as any user-specific files (e.g., ~/.tcshrc).

Bourne shell
  The original Bourne shell has one file that it reads when you log in: it's called .profile and is in your home directory. Put all your setup commands there. Later versions of the Bourne shell may also read /etc/profile before your local setup file is read and may also read the contents of whatever file is named in the ENV environment variable (Section 35.3) (but only for interactive shells). You may set this variable from your own .profile:

  >     ENV=$HOME/.mystartup; export ENV

  The Bourne shell doesn't read .profile when you start a nonlogin shell or subshell (Section 43.7), though. Subshells are set up through inheritance of environment variables (Section 35.3) that were set when you first logged in (in system-wide setup files or .profile) or from commands you typed since.

C shell
  C shell users have several shell setup files available:

  - The .cshrc file is read any time a C shell starts -- that includes shell escapes and shell scripts.[4] This is the place to put commands that should run every time you start a shell. For instance, shell variables like cdpath (Section 31.5) and prompt should be set here. Aliases (Section 29.2) should, too. Those things aren't passed to subshells through the environment, so they belong in .cshrc (or .tcshrc). See the upcoming section on tcsh for more details.

    > [4]If you write a csh (or tcsh) script, you probably should use the -f option to keep scripts from reading .cshrc (or .tcshrc). However, you probably shouldn't use csh or tcsh for scripts.

    Alternately, you can put aliases into a separate file and use the source command to read the file into the current shell from your .cshrc/.tcshrc -- if you're the sort who likes to have custom init files for every host you log in to, but like your aliases to be common wherever you go. This provides a quick and easy way for you to copy your .csh.aliases (or whatever name you give it, being careful to distinguish between it and the slightly different format required by bash aliases) from host to host without clobbering your custom, localized init files.

  - When csh starts up, on recent systems it may read a system-wide setup file, such as /etc/csh.cshrc,[5] and for login shells, /etc/csh.login.

    > [5]On Mac OS X, /etc is a symbolic link to /private/etc. The actual initialization files for tcsh are in /usr/share/init/tcsh.

  - Your .login file is read when you start a login shell. You should set several things here. Set environment variables (Section 35.3) (which Unix will pass to subshells automatically). Run commands like tset (Section 5.3) and stty (Section 5.7, Section 5.8) that set up your terminal. Finally, include commands you want to run every time you log in -- checking for mail and news (Section 1.21), running fortune, checking your calendar for the day, etc.

    Note that .cshrc is read before .login, by csh, but that tcsh may be compiled such that the order is reversed, and .tcshrc may be read after .login in some environments. Check the version shell variable to find out how your environment is set up.

  - The shell reads .logout when you end a login shell. Section 3.8 has tips for reading .logout from nonlogin shells.

Korn shell
  The Korn shell is a lot like the Bourne shell. A login Korn shell (Section 3.4) will read the .profile first; recent versions do so only after reading /etc/profile, if present. The .profile can set the ENV (Section 35.5) environment variable to the pathname of a file (typically $HOME/.kshrc). Any child Korn shell started by that login shell -- including all subshells -- will read the file named by `$ENV` as it starts up, before printing a prompt or running other commands.

  The public domain Korn shell often found on Linux may also be further restricted when invoked as a "privileged" shell, using a pattern that matches r*sh, in which case neither the ~/.profile nor the file named by the ENV environment variable will be read. Instead, the shell will be initialized using /etc/suid_profile, if present.

bash
  bash is something of a cross between the Bourne and C shells. A login bash will read .bash_profile , .bash_login, or .profile. A noninteractive bash will read a file named .bashrc in your home directory. The shell reads .bash_logout when you end a login shell; you can set a trap (Section 4.18) to handle nonlogin shells.

  bash also uses GNU Readline for reading and editing text you enter at a shell prompt. The .inputrc file configures Readline for a given user; /etc/inputrc is for global configuration.

tcsh
  tcsh is like the C shell but more flexible. If a tcsh shell is run, it first tries to read .tcshrc and, if not found, then tries .cshrc. In addition, tcsh will also load either .history or the value of the histfile variable, if set; then it may try to read .cshdirs or the value of the dirsfile variable.
zsh
  As always, zsh is very flexible. Startup files are read from the directory named in the ZDOTDIR environment variable, if any;[6] otherwise, from HOME. All shells read the global /etc/zshenv and your .zshenv files. If the shell is a login shell, commands are read from /etc/zprofile and then your .zprofile. Then, if the shell is interactive, commands are read from /etc/zshrc and your .zshrc. Finally, if the shell is a login shell, /etc/zlogin and your .zlogin files are read.

  > [6]ZDOTDIR may be hard to set on your first login -- when your zsh is a login shell -- because it's hard to set an environment variable before your first shell starts. (The system program that starts your shell, like login(1), could do the job, I guess.)

--JP and SJC

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