Jump to top of page
Names of Initialization and Logout Files
|
The names used by the C-Shell family for
initialization and logout files are
straightforward. The login file is
.login; the environment file is
.cshrc for the C-Shell and
.tcshrc for the Tcsh; and the logout
file is .logout. For backwards
compatibility, if the Tcsh can't find a file
named .tcshrc, it will look for one
named .cshrc, which only makes sense.
The names used by the Bourne shell family take
a bit of explanation. To start, we need to
recall an important idea from Chapter 11.
In the early 1990s, a set of specifications
called POSIX 1003.2 was created to describe a
"standard" Unix shell. For the most part, the
POSIX standard was modeled after the Bourne
shell family. Indeed, today's modern Bourne
shells (Bash, Korn shell, FreeBSD shell) all
conform to the 1003.2 standard.
The POSIX standard mandates that a shell
should support both a login file and an
environment file, but not necessarily a logout
file. The name of the login file should be
.profile. However, to retain
flexibility, the name of the environment file
is not fixed. Instead, an environment
variable named ENV should hold the name
of the environment file. For example, if you
are a Korn shell user, you might set the value
of ENV to .kshrc. (We'll talk
about filenames later.)
If you look at Figure 14-1, you will see
that the Korn shell follows the POSIX
specification: The name of the login file is
.profile, and the name of the
environment file is stored in the ENV
variable.
Bash is different because it was created by
very clever programmers (see Chapter 11)
who designed it to run in two different modes:
default mode, for power and flexibility(*),
and POSIX mode for compatibility. In default
mode, Bash supports enhancements over the
POSIX standard; in POSIX mode, Bash strictly
adheres to the 1003.2 standard.
In general, the Bash default mode is just fine, and
that is what most people use most of the time.
However, if you ever have a need for a POSIX-compliant
shell, say, to run a special shell script, you can
always run Bash in POSIX mode(*).
In default mode — which is what you and I
would normally use — Bash looks for a login
file named either .bash_profile or
.bash_login (use whichever one you
want), and an environment file named
.bashrc.
In POSIX mode, Bash follows the same rules as
the Korn shell. The login file is named
.profile, and the name of the
environment file is stored in the ENV
variable.
In both modes — the default mode and the POSIX mode —
Bash uses a logout file named .bash_logout.
You should now be able to understand all of
Figure 14-1, which means we can turn our
attention to a very important question: What
types of commands should you put in your
initialization files and in your logout file?
Before I lay the groundwork for answering that
question, I want to make two quick
digressions, one to explain about dotfiles and
rc files, the other to talk about what
you need to know in order to create and edit a
file.
Jump to top of page
When you look at the filenames in
Figure 14-1, you will notice two odd
things. First, all the names begin with a
dot; second, the names of the environment
files end with rc.
Files whose names start with a period are called
DOTFILES or HIDDEN FILES. We will discuss them in
Chapter 24 but, to help you now, here is a summary
in advance.
There are many files that, for one reason or
another, you want to ignore most of the time.
Usually, these are configuration files that
are used silently by some program or other. A
good example of this are the shell
initialization files we have been discussing.
As we will discuss in Chapter 24, the
command you use to list your files is
ls. As a convenience, ls will not
list any names that begin with a dot unless
you use the -a (all files) option.
Thus, when you use ls in the usual
manner, you won't see the names of any of your
dotfiles.
This is why all the initialization and logout
files have names that begin with a dot. Once
you set up the files the way you want, there
is no reason to think about them unless you
want to make a change. In particular, you
don't want to look at their names every time
you list your files.
If you ever do want to list all your
files, including the dotfiles, just use ls
-a. To see how it works, take a moment to
try both commands:
ls
ls -a
Moving on, you will notice that the environment
files have names that end with the letters
rc: .bashrc, .cshrc and
.tcshrc. This is a common convention
used by Unix programs for naming
initialization files. For example, the
vi and ex editors (which are
related) use an initialization file named
.exrc; and the generic Unix email
program, mail, uses an initialization
file called .mailrc.
As you work with Unix over the years, you will
encounter a great many rc files. As a
general rule, such files are used to hold
initialization commands and, almost always,
they will be dotfiles to hide them from the
ls command.
What's in a Name?
rc Files
Many Unix programs use configuration files
whose names end in rc, for example,
.bashrc, .tcshrc and
.exrc. The designation rc
stands for "run commands": commands that are
run automatically each time a particular
program starts.
The name derives from the CTSS operating
system (Compatible Time Sharing System),
developed at MIT in 1963. CTSS had a facility
called "runcom" that would execute a list of
commands stored in a file. Some of the early
Unix programmers had used CTSS and, when they
created configuration files, they chose names
that ended in rc.
This was the start of a long-standing
tradition among Unix programmers of naming
initialization files by using dotfiles whose
names end in rc. For example, if you
wrote a program called foo, you would
probably name the initialization file
.foorc. That is why, earlier in the
chapter, I suggested that, if you are a Korn
shell user, you should name your environment
file .kshrc.
When we talk about such files, we pronounce
rc as two separate letters. For
example, .foorc is "dot-foo-R-C". For
reference, Figure 14-2 shows the
pronunciations for the most common environment
files. Knowing how to pronounce such names is
important when you talk to other Unix people.
Figure 14-2: Pronouncing the names of rc files
Many Unix programs use initialization files
whose names start with a dot (period) and end
with the letters rc. The dot keeps the
names from being displayed when you list your
files; the rc is a abbreviation for
"run commands". (See text for a full
explanation.) This table lists the names of
the most common shell environment files, along
with the most common pronunciation for each
name. Can you see the pattern?
Environment File |
Pronunciation |
.cshrc | "dot-C-shell-R-C" |
.tcshrc | "dot-T-C-shell-R-C" |
.bashrc | "dot-bash-R-C" |
Jump to top of page
Using a Simple Text Editor
|
In order to be a skillful Unix user, you must be able
to edit (modify) text quickly. This is especially true
if you are a programmer. Specifically, your login
file, environment file, and logout file all contain
text and, in order to create or modify these files, you
need to be able to use a text editor program.
The two main Unix text editors are vi and Emacs
and, eventually, you will need to master one of them.
However, both vi and Emacs are complex. In
fact, within this book, I have devoted an entire
chapter to vi (Chapter 22). Reading this
chapter, or teaching yourself Emacs, will take some
time, so I have some alternatives for you. If you use a
desktop environment such as Gnome or KDE (see
Chapter 5), there will be a simple GUI-based
editor you can use to create and modify small text
files. If you use the CLI (command line interface),
there will probably be a simple text-based editor you
can use until you learn vi or Emacs.
Let's start with the desktop environment. There are
two ways to access the GUI-based editor. First, you
can start it from within the menu system. You will
most likely find it listed under "Accessories". Second,
you can start the program from a command line. Just
open a terminal window (see Chapter 6), wait for
the shell prompt, and enter the name of the program.
With KDE, the GUI-based text editor is kedit;
with Gnome, it is gedit.
Most Linux systems will have KDE or Gnome, but even if
you don't use Linux, try running gedit anyway.
It's part of the GNU utilities (Chapter 2) and, as
such, you will find it on many different systems. For
example, you can run gedit from a Solaris
terminal window under JDS (the Java Desktop System).
If you don't have access to a GUI-based editor, there
is a good chance your system will have a simple
text-based editor. The most common ones are Pico and
Nano. (They are pretty much the same; Nano is the GNU
version of Pico.) To check if your system has one of
these editors, see if you can display one of the man
pages. If so, you can use the man page to teach
yourself the basics:
man pico
man nano
Once you figure out how to use one of the simple text
editors — either a GUI-based text editor or Nano/Pico —
you can use it to create and edit your initialization
and logout files. However, remember what I said: such
programs are only for beginners. In the long run, you
need to learn either vi or Emacs.
Jump to top of page
Login Shells and Non-Login Shells
|
In Chapter 12, we talked about interactive and
non-interactive shells. You use an interactive shell
when you enter commands at the shell prompt; you use a
non-interactive shell when you run a shell script. In
order to understand how to use initialization files, we
need to go a bit further in our analysis, because there
are two different types of interactive shells.
Whenever you log in, the shell that starts is
called a LOGIN SHELL. All other interactive
shells are called NON-LOGIN SHELLS. The
distinction is important because
initialization files are processed differently
for login shells than for non-login shells.
Let's consider a few common situations.
1. Virtual consoles and terminal windows
When you use a desktop environment, such as
Gnome or KDE, there are two ways to get to a
shell prompt: you can open a terminal window,
or you can change to a virtual console (see
Chapter 6). When you use a virtual
console — say, by pressing <Ctrl-Alt-F1>
— you are required to log in. When you do, a
login shell starts. On the other hand, if you
simply open a terminal window, a non-login
shell starts (because you did not log in).
2. Starting a new shell
At any time, you can start a new shell by
entering its name. For example, say you are
using Bash, and you want to try the Tcsh.
Just enter the tcsh command. The new
shell is a non-login shell (because you did
not log in).
3. Using a remote host
To connect to a remote Unix host, you use the
ssh (Secure Shell) program. Once
ssh makes the connection for you, you must
log in. Doing so starts a login shell.
Jump to top of page
When Are Initialization Files Executed?
|
Now that you understand the difference between
a login shell and a non-login shell, we can
discuss what happens when a new shell starts.
The important question to answer is: Which
initialization files are executed and when?
There are two general rules, with minor
variations. Let's start with the rules.
1. A login shell executes your login file
and your environment file.
2. A non-login shell only executes your
environment file.
Here are the specific details, starting with
the members of the Bourne shell family. As a
shortcut, I will use $ENV to represent
the file whose name is stored in the
$ENV environment variable. For example,
for the Korn shell, you might set the value of
$ENV to be .kshrc.
Bash (default mode)
• Login shell: .bash_profile
• Non-login shell: .bashrc
Bash (POSIX mode)
• Login shell: .profile, then $ENV
• Non-login shell: $ENV
Korn shell
• Login shell: .profile, then $ENV
• Non-login shell: $ENV
Before we move on to the C-Shell family, let
me make a few comments. First, you will
notice that we can divide all the Bourne
shells into two groups. Two of the three
shells follow the POSIX convention of using
.profile and $ENV. The
exception is Bash in default mode. This is an
important insight because, once you have used
shells for a while, you will see that there is
something different about Bash.
Bash reflects the attitudes of the young
programmers who came of age in the mid- to
late 1990s, during the growth of Linux and the
open source movement (see Chapter 2).
Emotionally, the open source programmers felt
a bit like outlaws, rebelling against
commercial Unix conventions, such as
proprietary software and restrictive licensing
agreements. For this reason, they opted to
create an enhanced shell that was more than
just a clone of the standard POSIX shell(*).
This is why, as a Bash user, you will
encounter many situations in which Bash
behaves differently than other shells.
For example, it is only the Bash login shell
that executes a login file and not an
environment file. With all other shells, a
login shell executes both the login
file and the environment file, in that order.
This means that Bash users must put a special
command in their login file to force it to
execute the environment file. (I'll show you
how to do this.)
Moving on, let's take a look at how the
members of the C-Shell family use
initialization files:
C-Shell
• Login shell: .cshrc, then .login
• Non-login shell: .cshrc
Tcsh
• Login shell: .tcshrc, then .login
• Non-login shell: .tcshrc
(For backwards compatibility, if the Tcsh
can't find .tcshrc, it will look for
.cshrc.)
This pattern is straightforward, except for
one interesting anomaly. In the C-Shell
family, login shells execute the environment
file first. In the Bourne shell family,
login shells execute the login file first. To
understand why this is the case, we need to
talk a bit about the history of initialization
files.
Jump to top of page
A Quick History of Shell Initialization Files
|
(In this section, I am going to talk a bit
about the history of the shell. For more
details, see Chapter 11.)
The original Unix shell was written by Ken
Thompson and used at Bell Labs in the early
1970s. This shell did not make use of a
standardized initialization file. In the
mid-1970s, Bell Labs programmers wrote two new
replacement shells: the Mashey shell (also
known as the PMB shell) and the Bourne shell.
A programmer named Dick Haight added support
for an initialization file (.profile)
to the Mashey shell. Later, the same feature
was added to the Bourne shell.
The .profile file was executed only
once, when you logged in. In 1987, when Bill
Joy developed the C-Shell at U.C. Berkeley, he
enhanced the initialization process by using
two files instead of one. The first file,
.cshrc, ran every time a new shell
started. The second file, .login, ran
only when a login shell started. Thus, it
made sense to execute .login after
.cshrc, as its job was to run only
those extra commands that were necessary at
login time.
In 1982, David Korn of Bell Labs developed
another replacement for the Bourne shell, the
Korn shell. Korn adopted Bill Joy's idea of
using two initialization files, what we now
call an environment file (.cshrc) and a
login file (.login). Because Korn
worked at Bell Labs, which was a Bourne shell
shop, he used the name .profile for the
login shell. When it came time to the name the environment file, Korn decided to let the
users choose the name for themselves, by
setting the ENV variable to the name of
the environment shell. In this way, you could
have more than one environment file for
different purposes.
However, once he made this decision, Korn had
to ensure that the login file executed
before the environment file. Otherwise,
there would be no way for a user to set the
ENV variable.
That is why, to this day, Bourne family shells
run the login file first, and the C-Shell
family shells run the environment file first.
In practice, this is usually not a big deal,
but it is something to remember if you ever
have a mysterious initialization problem that
seems insolvable.
Jump to top of page
What to Put in Your Initialization Files
|
We can now consider the questions I posed a while back: What should you put in your login file? What should you put in your environment file? Here are the answers.
Your login file has two jobs: to set up your
environment and to initialize your work
session. Thus, your login file should contain
commands to (1) create or modify environment
variables, and (2) perform all one-time
actions.
The login file, then, is where you set
variables such as PATH, PAGER,
and so on, and use umask to set your
file creation mask (Chapter 25). If the
login file is for a remote host, you may also
need to use stty to modify key mappings
(Chapter 7). Finally, you may want to
display a personal message or other
information each time you log in.
As we discussed earlier in the chapter, the
environment is automatically inherited by all
child processes, including new shells. Thus,
you only need to set environment variables
(such as PATH) once, in your login
file. It makes no sense to set an environment
variable in your environment file, where it
will be reset every time a new shell starts.
Your environment file has a different job: to
set up whatever customizations cannot be
stored in the environment, in particular,
shell options, aliases and functions. Because
these settings are not stored in the
environment, they must be recreated every
time a new shell starts.
Jump to top of page
Displaying, Creating and Editing Your Initialization Files
|
You may already have one or more initialization
files. On a shared system, such files are
often created by the system administrator. On
your own system, they may be generated
automatically at the time your account was
created. If you already have such files, you
can modify them to suit your needs. If not,
you can create the files yourself.
Initialization files are kept in your home
directory (your personal directory; see
Chapter 23). As we discussed earlier,
all initialization files are dotfiles, which
means their names start with a .
(period). For reference, Figure 14-1,
earlier in the chapter, contains the names of
the standard initialization files.
As we discussed earlier, you display the names
of all your dotfiles by using the the
ls -a command. (Without the
-a option, ls won't show
dotfiles.) If the list is too long, you can
send it to less:
ls -a
ls -a | less
Once you see which initialization files you
have, you can look at their contents by using
less. One of the following commands
should do the job:
less .bash_login
less .bash_logout
less .bash_profile
less .bashrc
less .cshrc
less .kshrc
less .login
less .logout
less .profile
less .tcshrc
To create or modify a dotfile, you need to use
a text editor. If you already know vi
or Emacs, great. If not, you can — for now —
use one of the simpler editors we discussed
earlier, kedit or gedit.
Because these are GUI-based editors, you must
use them from within a desktop manager. You
can't use them from a virtual terminal or from
a CLI connected to a remote host.
Starting from your GUI, open a terminal window
and enter the the name of the editor, followed
by the name of the file you want to create or
edit. With KDE, use kedit; with Gnome,
use gedit. For example:
kedit .bash_login
gedit .bash_login
A new window will open. If the file already
exists, it will be loaded, allowing you to
modify the contents. If the file does not
exist, you will have an empty window, allowing
you to create the file.
Jump to top of page
Comments in Shell Scripts
|
The initialization files we have been
discussing are actually shells scripts:
programs that are written in the language of
the shell and executed by the shell. In a
moment, we will take a look at some sample
scripts. Before we do, I want to explain an
important point regarding shell scripts and
programs in general.
Take a look at the initialization files
in Figure 14-3, 14-4, 14-5 and 14-6.
Although they are quite different from one
another, you will notice they have one thing
in common: many of the lines begin with a
# (hash or pound) character. Such lines
are called COMMENTS.
As a script is executed, the shell ignores all
the comments. This allows you to put in notes
to help you remember the logic and understand
the script. If you have never programmed
before, you might think comments should not be
necessary when you write scripts for your own
use. Surely, when you read a script at a
future date, you will remember the logic
behind the various commands. After all, you
are the one who wrote the script in the first
place.
The truth is, although your reasoning may be
clear right now, when you read a shell script,
or any program, even a few days later, you
will have trouble remembering what you
were thinking at the time. This is why all
experienced programmers put lots of comments
in everything they write.
Moreover, the time may come when someone else
will need to read your scripts. In such
cases, comments are invaluable. My advice is
to document what you are doing, as you are
doing it. Pretend that everything you write
will have to be understood by another person.
Later, you will be that person and, believe
me, you will never be sorry you took the time
to put in comments(*).
Within a shell script, the actual definition of
a comment is a # character and
everything the follows it to the end of the
line. Thus, a comment can take up all or part
of a line. Consider the following example:
# Display the time, date, and current users
date; users
The first line is a comment; the second line
contains two commands with no comments. When
the shell executes these two lines, it will
ignore the comment and run the commands on the
second line. Now consider:
date; users # Display time, date, and current users
In this case, we have a single line, containing
two commands followed by a comment. When the
shell executes this line, it will run the
date command and users command, and
ignore everything else on the line. Thus,
when you write shell scripts, you have two
ways to put in a comment: at the end of a
line, or on a line by itself.
In the following few sections, we will take a
closer look at the sample initialization
files. As we do, think about how difficult
it would be to understand these files if there
were no comments.
Jump to top of page
Bourne Shell Family: Sample Initialization Files
|
In the next two sections, we will discuss four
sample initialization files. What you are
about to see will tie together everything you
have learned in the last three chapters:
interactive shells, environment variables,
shell variables, shell options,
metacharacters, quoting, the search path,
command substitution, the history list,
command line editing, aliases, and comments.
My intention is for you to adapt these files
for your own use, making whatever changes and
additions are necessary to serve your needs.
In this section, we will discuss
initialization files that are suitable for a
member of the Bourne shell family (Bash, Korn
shell). In the next section, we will discuss
initialization files for the C-Shell family.
Regardless of which shell you happen to use
right now, I'd like you to take a look at both
sections. Over the course of your life with
Unix and Linux, you will find yourself using a
variety of systems, and it will help you to be
familiar with the initialization files for
both shell families.
Our goal in this section is to take a close
look at a sample login file and a sample
environment file. You will find the login
file in Figure 14-3. I will remind you
that this is the file that is executed
automatically each time you log in. With
Bash, your login file will be named
.bash_profile or .bash_login.
With the Korn shell, or Bash in POSIX mode, it
will be .profile.
The environment file is in Figure 14-4.
This file is executed every time a new shell
starts. With Bash, your environment file is
named .bashrc. With the Korn shell or
Bash in POSIX mode, you can name the
environment file anything you want by setting
the ENV variable. My suggestion is to
use .kshrc for the Korn shell and
.bashrc for Bash.
With the Bourne shell family, the login file
is run first, before the environment file, so
we will discuss the login file first. (With
the C-Shell family, the environment file is
run first.)
Figure 14-3: Bourne shell family: Sample login file
The login file is executed automatically each
time you log in. Here is a sample login file
suitable for Bash or the Korn shell. Use this
file as a template and adapt it for your own
use. See text for details.
By now, you should understand most of the
commands, variables and options used in the
sample files. I'll go over each section for
you and, for reference, I'll tell you the
chapter in which you can find more information
should you need it.
Section 1 of the login file defines the
environment variables. We set the size of the
history list to 50 lines, the default paging
program to less, and the default text
editor to vi. We also add a specific
directory to the end of the search path.
(Chapter 12: variables; Chapter 13:
history list, search path; Chapter 21:
paging programs.)
Sections 2A and 2B define the shell prompt by
setting the PS1 environment variable.
Section 2A is for Bash; section 2B is for the
Korn shell. Use either 2A or 2B, but not
both. (Chapter 12: variables;
Chapter 13: shell prompt.)
Section 3 sets the file creation mask to
control the default permissions for newly
created files (Chapter 25: file
permissions, umask.)
Section 4 is used only for login files on a
remote host. You do not need this section
when you are using Unix or Linux on your own
computer. The stty command sets the
key mapping for the erase signal. I
have given you two possible commands: use
whichever one works best with your keyboard.
(Chapter 7: erase signal,
stty.)
Section 5 displays a welcome message. You can
change this to whatever you want.
(Chapter 8: date; Chapter 12:
echo, command substitution.)
Section 6 displays interesting information
about the system. (Chapter 4:
last; Chapter 8: whoami,
users, uptime; Chapter 12:
echo, command substitution;
Chapter 15: pipeline; Chapter 16: head.)
Sections 7A and 7B make sure the environment
file is run. Section 7A is for Bash. It
checks to see if a file named .bashrc
exists. If so, it tells the shell to run the
file. Section 7B is for the Korn shell. It
sets the value of the ENV environment
variable to the name of the environment file.
Use either 7A or 7B, but not both.
(Chapter 12: variables; Chapter 14:
environment files.)
Section 8 is for the Korn shell only. By
default, the Korn shell does not support a
logout file, the file that is executed
automatically each time you log out. However,
you can simulate a logout file by trapping the
EXIT signal, which is generated when
you log out. Here, we specify that when the
EXIT signal occurs, the file named
.logout should be executed.
(Chapter 7: trapping a signal;
Chapter 14: logout files.)
With the Bourne shell family, the environment
file is simpler than the login file, because
the login file does most of the work. All the
environment file needs to do is re-create
whenever is lost when a new shell is started:
shell options, aliases and functions. Take a
look at Figure 14-4, where you will see a
sample environment file.
Figure 14-4: Bourne shell family: Sample environment file
The environment file is executed automatically whenever
a new shell starts. Here is a sample environment file
suitable for Bash or the Korn shell. Use this file as
a template and adapt it for your own use. See text for
details.
Section 1 sets the shell options. The
ignoreeof option requires us to use a
logout or exit command to log
out. By trapping the eof signal, we
keep ourselves from logging out accidentally
by pressing ^D one too many times.
(With Bash, you can set the IGNOREEOF
environment variable instead of using the
shell option.) The second shell option sets
Emacs for our command line editor. Strictly
speaking, you don't need to set this option,
as Emacs is the default. However, I like to
set it explicitly as a reminder. Finally, we
set the noclobber option to protect us
from accidentally deleting the contents of a
file when we redirect standard output.
(Chapter 7: trapping the eof signal;
Chapter 12: shell options, command line
editing; Chapter 15: redirecting standard
output.)
Section 2 sets the aliases. They include an
abbreviation for the alias and
date commands; several variations of the
ls command; the del alias to
help us avoid deleting the wrong files; and
the r and h aliases to help us
use the history list. (Chapter 8:
date; Chapter 12: history list,
aliases; Chapter 24: ls.)
Section 3 is reserved for any shell functions
we may want to define. A function allows you
to create your own customized commands by
writing a small program. Learning to write
such programs is beyond the scope of this
book. However, if do use functions, this is
the place to define them.
Jump to top of page
C-Shell Family: Sample Initialization Files
|
In this section, we will discuss two sample
initialization files for the C-Shell family
(C-Shell and Tcsh). What you are about to
read here will tie together everything you
have learned in the last three chapters. My
intention is to explain the contents of these
sample files so you can adapt them for your
own use by making whatever changes and
additions are necessary to serve your needs.
We'll start with the environment file in
Figure 14-5. I will remind you that this
is the file that is executed automatically
whenever a new shell starts. With the
C-Shell, this file is named .cshrc.
With the Tcsh, it can be named either
.tcshrc or .cshrc. After
discussing the environment file, we will move
on to Figure 14-6, which contains a
sample login file: the file that is executed
whenever you log in. With both shells, this
file is named .login.
We are starting with the environment file
because, in the C-Shell family, it is run
first, before the login file. (With the
Bourne shell family, the login file is run
first.)
|