CONFIGURING THE BASH SHELL: VERSION 1.0
Bash is an acronym for Bourne Again SHell. It is compatible with the original Bourne shell and boasts some enhancements, like command line editing [TRANSLATION: The Bash shell can run program written for the Bourne shell, plus it offers so much more than the Bourne shell]. It is also the default Linux shell and is the most widely used shell in Linux. For those who do not know, a shell is a program that acts as an intermediary between the user and the kernel [TRANSLATION: A shell is a program that takes commands from the user and passes them into the kernel for processing]. Like most of the software that comes with Linux,bash
is highly configurable.ASSUMPTIONS
This article makes a few assumptions about you; the reader:
You know basic Linux commands, eg:
ls
,cd
,mv
, etc...You know how to use a text editor, eg:
vi
,emacs
,pico
, etc...You know how to read path names, eg:
/etc/profile
You know a little
bash
shell scripting.
While this article can be read without meeting all the said assumptions, it would benefit you more if you did.
THE CONFIGURATION FILES
bash
has five common configuration files. They are not always found on every Linux distribution, but they are not hard to create. These files are as follows:
/etc/profile
/etc/bashrc
~/.bash_profile
~/.bashrc
~/.bash_logout
The files are categorized into two groups: global and local. Global files are those that contain configurations that affect all users who use
bash
. Global files are usually located in/etc
. Local files contain personal configurations for the user, and affect only the specific user who is using them. They are normally hidden files [TRANSLATION: They start with a '.' like~/.bashrc
] found in the user's home directory. If you do not have these files, do not worry. After reading this tutorial, you should be able to create your own. For now, an explanation on each configuration file.
/etc/profile
/etc/profile
is the global system configuration forbash
which controls the environmental variables and programs that are to be run whenbash
is executed [TRANSLATION:/etc/profile
contains variables and programs that are executed for every user who runsbash
]. If you are an MS-DOS user,/etc/profile
is equivalent toautoexec.bat
.
/etc/bashrc
/etc/bashrc
is the global system configuration forbash
which controls the aliases and functions to be run whenbash
is executed [TRANSLATION:/etc/bashrc
contains aliases ("shortcuts" to long commands) as well as pieces of code that are executed when they are called for]./etc/bashrc
is sometimes omitted, and its contents placed into/etc/profile
.
~/.bash_profile
~/.bash_profile
is the local system configuration forbash
which controls the environment variables and programs that are run whenbash
is executed. These environment variables and functions are specific only to the user, and they do not affect anyone else. This file is executed right after the global configuration file/etc/profile
is executed [TRANSLATION: Unlike/etc/profile
which affects all users,~/.bash_profile
affects only the user runningbash
].
~/.bashrc
~/.bashrc
is the local system configuration forbash
which controls the aliases and functions to be run whenbash
is executed. These aliases and functions are specific only to the user, and they do not affect anyone else. This file is executed right after the global configuration file/etc/bashrc
is executed [TRANSLATION: Unlike/etc/bashrc
which affects all users,~/.bashrc
affects only the user runningbash
].
~/.bash_logout
~/.bash_logout
is the local system configuration forbash
which runs programs right before the user is logged out. These programs are specific only to the user running them, and they do not affect anyone else.
EXPLAINING VARIABLES
A variable is a named storage location in the computer's memory. When you define a variable, this location holds the variable's defined value [TRANSLATION: Think of a variable as a box called Box A. Whatever you put in Box A, say a ball, is the value of Box A]. There are two types of variables inbash
: environmental variables and local variables. Environmental variables are those that are created by the system, and are normally defined in/etc/profile
. These variables (which will be explained later) includeSHELL
,PS1
,PATH
, etc... Local variables are those that are defined by the user, and are usually placed in the local configuration files like~/.bashrc
. These variables are local only to the user whenbash
is executed [TRANSLATION: Environment variables affect everyone who runsbash
, while local variables affect only those who specify them in their local configuration files].
Defining variables
A variable definition consists of three parts. A variable_name, the assignment operator: "=
" and a variable_value. The variable_name is the name of the variable, and the variable_value is the value to be assigned to the name. Eg:
variable_name=variable_value
Using the box analogy, variable_name is Box A, and variable_value is the ball. Hence, variable_name's value is a ball. Notice that there are no spaces beside the assignment operator. When a variable is defined, it has to be made available to programs the user uses. This is done by exporting the variable with the
export
command:
export variable_name
Accessing variables
Variables can be accessed by prefixing the variable_name with a dollar sign: "$
". So for example, to view your environment SHELL variable, type the following command:
xconsole$ echo $SHELL
/bin/bash
This means that the variable variable_name is expanded to variable_value when you prefix it with a "
$
" symbol. Understanding how to manipulate variables is essential when configuringbash
, as its configuration files are all inbash
shell syntax. Now that the worst is over, we can begin with the actual configuration.
COMMENTING AND UNCOMMENTING
If while editing your configuration files, you find a line of code that you are unsure of, you can comment it out instead of deleting it. Commenting is the process of "removing" a particular line by placing special characters in front of it, so that you do not really delete it from the file. A commented line will not be read by the configuration file, so it is just as good as deleting it. Here is an example:
FOOBAR=/bin/foobar
To comment this line out so that it will not be read by the configuration file, add the hash symbol: "
#
" in front of it:
# FOOBAR=/bin/foobar
If you decide later that you want this line back, just remove the hash symbol. Commenting is also good for small notes when editing:
# not sure what this variable does, so I decided to comment it out
# 1 May 1999
# FOOBAR=/bin/foobar
It is a good idea to add useful notes like these so that you will know what you did when you need to reconfigure your files much later on.
PATH
The first thing to configure is thePATH
variable.PATH
defines the directories that you have direct access to. For example; if you have a program called foo in/bin
and you want to run it. If/bin
is in yourPATH
, then all you have to do is to type foo anywhere and the program would run. If/bin
was not in yourPATH
, you would have to type the full path name to program foo in order to run it, that is:/bin/foo
. This variable is located in/etc/profile
, and it has an unusual syntax. Each directory on the right hand side of the equation has to be separated by a colon: ":
". Eg:
PATH=/bin:/usr/bin:/usr/local/bin
export PATH
In the above example, three directories,
/bin
,/usr/bin
, and/usr/local/bin
are separated by a colon. When creating a newPATH
variable, it is important to add the currentPATH
variable to the newPATH
variable. Eg:
PATH=$PATH:/usr/games
export PATH
This appends
/usr/games
into the already existingPATH
variable, which is$PATH
. Recall that a variable prefixed with a dollar sign is expanded to its original value. In this case,$PATH
is expanded to/bin:/usr/bin:/usr/local/bin
. Because it is added to the newPATH
variable, the newPATH
variable can now be expanded to/bin:/usr/bin:/usr/local/bin:/usr/games
. If you had omitted$PATH
in the definition, thenPATH
would be expanded to/usr/games
. If you are not root, you may add to and modify your current existingPATH
in~/.bash_profile
.
PROMPTS
ThePS1
variable is your primary prompt. Depending upon how your system is configured, thePS1
variable will vary.PS1
is normally defined in/etc/profile
, but can be overridden by defining it again in~/.bash_profile
[TRANSLATION: Because/etc/profile
is only writable by root, you can only override the environmental variables there by redefining them in your~/.bash_profile
].bash
recognizes special characters prefixed with a backslash for thePS1
variable. These characters are:
\t the current time in HH:MM:SS format
\d the date in "Weekday Month Date" format (eg, "Tue May 26")
\n newline
\s the name of the shell
\w the current working directory
\W the basename of the current working directory
\u the username of the current user
\h the hostname
\# the command number of this command
\! the history number of this command
\$ if the effective UID is 0, a #, otherwise a $
These are the characters that allow you to change your prompt. If your
PS1
variable is set asPS1="[\u@\h \W]\$"
, then your prompt will look like this:
[xconsole@localhost /etc]$
If you were to change it to the following:
PS1="[\t \s]\$ "
, you would get:
[12:18:24 bash]$
In addition to these special backslash characters, you can use commands. For instance, to have your prompt run as a fortune, you can do this:
PS1="`fortune` \$ "
Notice that you have to use "
`
" instead of "'
". This changesPS1
to the following:
He is no lawyer who cannot take two sides. $
As you can see,
bash
is very lenient about the way you configure it, so knock yourself out. ThePS2
variable is your secondary prompt and is used when you have typed an incomplete command, or when you have typed a backslash at the end of a command [TRANSLATION: A backslash at the end of a command inbash
tells it that you are not done with the command. This is when it will present you with thePS2
variable.bash
is also smart enough to know when the command you are typing is incomplete, and in such a case, it will present you with thePS2
variable]. When you are presented with thePS2
variable,bash
expects you to finish the command before it will attempt to run it. To see your currentPS2
variable, run the following command:
x
console$ if [ -f /etc/profile ]; then
When you press ENTER, you will see that you have a new prompt:
xconsole$ if [ -f /etc/profile ]; then >
This prompt is the
PS2
variable. You can also view it withecho $PS2
. In the above example with theif
statement, we did not add a backslash character right at the end of the command, butbash
knew the command was incomplete. As withPS1
, it is defined in/etc/profile
, and can be overridden and redefined in~/.bash_profile
. It recognizes the special backslashed characters, as well as other programs likefortune
[TRANSLATION: Whatever applies toPS1
, applies toPS2
as well].
HISTORY
bash
keeps a record of all the commands you type on the console. Depending on how it is configured, it may choose to save this file to a file called~/.bash_history
.bash
also keeps track of the commands you run, so that you can view them when you press the up arrow, or when you typehistory
. If you are concerned about your privacy, all this can be configured by playing with the following variables:
HISTSIZE
HISTFILE
HISTFILESIZE
These files are normally defined in
/etc/profile
, but can be overridden by including them in~/.bash_profile
.
HISTSIZE
HISIZE
controls the number of commands to remember in the history command. The default value is 500 [TRANSLATION:HISTSIZE
is what keeps track of the number of commands to be kept in history. That is, if it is specified with the value 5, thenhistory
will only remember the last 5 commands run]. Normally I assign it the value 5.
HISTFILE
HISTFILE
defines the file in which all commands will be logged to. Normally the value for this variable is set to~/.bash_history
. This means that whatever you type inbash
will be stored into the value ofHISTFILE
. I usually have no need for this file, so I either leave it undefined, or pipe the output to/dev/null
.
HISTFILESIZE
HISTFILESIZE
defines the maximum number of commands~/.bash_history
, or whatever value you assign toHISTFILE
, can hold. If it is defined as 2, then only the last 2 commands run will be logged to~/.bash_history
. The value ofHISTFILE
can grow pretty big if left unattended. This variable will ensure that it is kept to a specific size. The default value for it is 500. If you decide to have your commands logged toHISTFILE
, you may want to specify a smaller value than 500.
MAIL CHECKING
bash
allows you to configure how you want to check for emails.bash
has the following variables that control email configuration:
MAILCHECK
MAILPATH
MAIL_WARNING
These variables are normally defined in
/etc/profile
, but may be overridden in~/.bash_profile
When email is delivered to a user, the contents of the email are stored in a file. This file is defined by/var/spool/mail/$USER
[TRANSLATION: If your user name is xconsole, then your email is kept in/var/spool/mail/xconsole
] by default ifMAILPATH
is not defined. Changing this value will change the file in which your email is stored in.
MAILCHECK
This variable defines how oftenbash
will check for incoming email. The default value is 60. This means thatbash
will check to see if you have any new emails every minute.
MAILPATH
This variable defines the paths to check for emails. Normally this value is set to/var/spool/maile
. Each path is to be separated by a colon: ":
". You can also modify this variable to print out a special message when you receive any new emails. For instance, if you defined this variable as:
MAILPATH='/var/spool/mail/xconsole "Yeah! Incoming message!"'
When you receive an email, this is what happens:
Yeah! Incoming message!
This message can be tailored in anyway you like of course.
MAILPATH
will begin by checking the path to/var/spool/mail/xconsole
and then informing you of the received email.
MAIL_WARNING
IfMAIL_WARNING
is set,bash
will inform you if you attempt to read an email that you have just read with the following message:
The mail in mailfile has been read
mailfile is the variable
pine
.
RECEIVING NOTIFICATION WHEN A JOB FINISHES
Depending upon howbash
is configured, you may or may not receive a message that a job you have run in the background is done [TRANSLATION: Programs run in the background are called jobs. Running a program in the background is done simply by adding an amperstand: "&
" right at the end of the command, egupdatedb &
]. When the job ends, you may have to press ENTER before you receive a message like:
[1]1+ Done updatedb
If you want this message to pop up automatically without you having to hit the ENTER key, then you have to set the
notify
variable in your/etc/profile
or your~/.bash_profile
. This can be done by adding the following entry into your/etc/profile
or~/.bash_profile
:
set -o notify
The variable
notify
will notify you the moment a job in the background is finished. To unset this variable, the command isunset +o notify
.
TIMEOUT
When opening up a newbash
session, you can specify how long to wait before the shell automatically terminates with theTMOUT
variable. The value of this variable is to be set in the number of seconds to wait for user input before the shell self terminates. If you add this to your/etc/profile
or to your/etc/.bash_profile
, as so:
TMOUT=60
bash
will terminate the session after one minute. Here is what happens after one minute of no user input:
xconsole$ timed out waiting for input: auto-logout
Linux 2.2.7
login:
As you can see, the user is immediately logged out and a new login prompt is issue. This can be a good security practice if you do not use password protected screen savers.
OVERWRITING PRECAUTIONS
Often, one has to work with redirection inbash
[TRANSLATION: Redirection is running a program, and then having its output redirected to another file, or program, instead of to the monitor]. An example of redirection is:
xconsole$ echo "Hello World" > ~/.test_file
xconsole$ echo "tcsh is better" >> ~/.test_file
The "
>
" operator is the redirect operator, and the ">>
" operator is the append operator. The first command saves the stringHello World
into a file called~/.test_file
.Hello World
will not be echoed to the screen at all! It must be read from the file~/.test_file
. The second command appends to the file~/.test_file
. This means that when~/.test_file
is read, this is what we get:
xconsole$ cat ~/.test_file
Hello World
tcsh is better
Now imagine that this is some very important file. While typing away on the keyboard, you accidentally type the following command:
xconsole$ echo "AUGH" > ~/.test_file
What happens here is that ~/.test_file is completely overwritten. Anything important, has been deleted and replaced:
xconsole$ cat ~/.test_file
AUGH
To prevent against this sort of accident, you can set the
noclobber
variable. This is done with the commandset -o noclobber
. When set, here is what happens when we try to overwrite a file:
xconsole$ echo "Testing..." > ~/.test_file
bash: ~/.test_file: Cannot clobber existing file
As you can see,
bash
prevents you from overwriting the file. If you want to overwrite it, you can do a force by using the ">|
" operator:
xconsole$ echo "Try" > ~/.test_file
bash: ~/.test_file: Cannot clobber existing file
xconsole$ echo "Try again" >| ~/.test_file
xconsole$ cat ~/.test_file
Try again
Here we see that when we issue the second command,
bash
no longer complains and performs the command. I suggest you set this variable on at all times. Have it in your~/.bash_profile
or/etc/profile
. It is really easy to type ">
" by accident when you meant to type ">>
". It is much harder to type ">|
". On the other hand, this could cause problems with shell programs that need to execute the ">
" operator [TRANSLATION: If the program you are running uses the ">
" operator, and you have thenoclobber
variable set, then you will get an error message when executing the shell program]. So it is really up to you if you want to set it or not. To unset this variable, the command isunset +o noclobber
ALIASES
Aliases are what you can call, "shortcut commands". If you want something done quick, you can do it with aliases. One example an alias can do is to allow you to typels -aF --color
just by typingls
, or anything else you like. An alias is normally defined in/etc/bashrc
or~/.bashrc
. Aliases look like this:
alias ls='ls -aF --color'
alias haha='ls -aF --color'
alias sl='ls -aF --color'
In the above, the commands
ls
,haha
,sl
, will all perform the same action when typed. That is:ls -aF --color
. This is the usefulness of aliases. One particular use of aliases is for safety precautions:
alias rm='rm -i'
alias mv='mv -i'
alias cp='cp -i'
In the above example, the commands
rm
,mv
, andcp
will all ask for confirmation before attempting to overwrite a file. This is a good thing so you do not have to type the long form command with options. Another example:
alias mycd='mount -t iso9660 /dev/cdrom /cdrom'
You can now mount the CDROM with the command
mycd
, although a much better way would be to actually edit/etc/fstab
, but this example serves the purpose as well. To find out what your current aliases are, you use thealias
command:
xconsole$ alias
alias cp='cp -i'
alias rm='rm -i'
alias mv='mv -i'
Aliases can also be set and unset while the shell is running. Setting an alias on a shell is done with the
alias
command. Example:
xconsole$ alias mydir='ls -alF'
You can also unset aliases with the
unalias
command:
xconsole$ unalias mydir
The
unalias
command has one option:-a
. This option allows you to unalias all currently set aliases.
FUNCTIONS
Functions normally go to/etc/bashrc
and~/.bashrc
. Functions are pieces of code that perform a special action when called upon from the shell. You will need to know bash shell scripting in order to use functions. Here is an example of a function that unpacks all tarballs in the current directory:
unpack()
{ for tarball in *; do tar xvzf $tarball done }
Now if you wanted to unpack all tarballs in a current directory, all you would have to do is to use the command
unpack
, and all tarballs will be unpacked. Of course this is a really simple function, and could have been used as an alias instead:
alias unpack='tar xvzf *.tgz'
However, the above function is very simple. You can write much more complex functions, depending on the job to be accomplished. You can put entire shell programs into the
/etc/bashrc
or the~/.bashrc
files and have them run just by typing their function name.
EXAMPLES
The following are examples of what thebash
configuration files can look like. Feel free to create and/or modify your own configuration files. It is your system, and you should decide how you want it to run.
/etc/profile
# /etc/profile: This file contains system-wide defaults used by
# all Bourne (and related) shells.
# Set the values for some environment variables:
export OPENWINHOME=/usr/openwin
export MINICOM="-c on"
export MANPATH=/usr/local/man:/usr/man/preformat:/usr/man:/usr/X11R6/man:/usr/openwin/man
export HOSTNAME="`cat /etc/HOSTNAME`"
export LESSOPEN="|lesspipe.sh %s"
export LESS="-M"
#export MOZILLA_HOME=/usr/local/netscape
export HISTSIZE=20
export HISTFILESIZE=20# Set notification when a job ends.
set -o notify# Set the default system $PATH:
PATH="$PATH:/usr/X11R6/bin:$OPENWINHOME/bin:/usr/games"# I had problems using 'eval tset' instead of 'TERM=', but you might
# want to
# try it anyway. I think with the right /etc/termcap it would work
# great.
# eval `tset -sQ "$TERM"`
if [ "$TERM" = "" -o "$TERM" = "unknown" ]; then
TERM=linux
fi# 'kvt' uses "xterm-color" which isn't recognized by programs like
# 'pine'
# or 'pico', so let's change it to the default "xterm":
if [ "$TERM" = "xterm-color" ]; then
TERM=xterm
fi# Set a default shell prompt:
PS1='[\u@\h \W]\$ '
PS2='> 'ignoreeof=10
export PATH DISPLAY LESS TERM PS1 PS2 ignoreeof# Default umask. A umask of 022 prevents new files from being
# created
# group
# and world writable.
umask 022# Set up the LS_COLORS and LS_OPTIONS environment variables for
# color
# ls:
eval `dircolors -b`# Notify user of incoming mail. This can be overridden in the
# user's
# local startup file (~/.bash.login or whatever, depending on the
# shell)
if [ -x /usr/bin/biff ]; then
biff y
fi# Print a fortune cookie for login shells:
echo
fortune /usr/games/lib/fortunes/fortunes
/usr/games/lib/fortunes/fortunes2
echo# Environment variables for the Qt package:
QTDIR=/usr/lib/qt
CPLUS_INCLUDE_PATH=$QTDIR/include:$CPLUS_INCLUDE_PATH
export QTDIR
export CPLUS_INCLUDE_PATH# KDE additions:
KDEDIR=/opt/kde
PATH=$PATH:$KDEDIR/bin
export KDEDIR PATH# Make sure that the current directory is always last in the PATH
# variable.
PATH="$PATH:."/etc/bashrc
# /etc/bashrc
# System wide functions and aliases
# Environment stuff goes in /etc/profile# functions go here
# create a new ~/.plan file at every log in
new_plan()
{
if [ -f `which fortune` ]; then
;echo > ~/.plan
;`which fortune -s` >> ~/.plan
;echo >> ~/.plan
fi
}# aliases go here
# paranoia
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'~/.bash_profile
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi# user specific environment and startup programs
PATH=$PATH:$HOME/bin:$HOME/garbage
BASH_ENV=$HOME/.bashrcexport PATH BASH_ENV ~/.bashrc
#.bashrc
# User specific aliases and functions
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi# create a log of all users who logged in,
# and those currently logged in
see_all()
{
LOG_FILE=/var/log/see_all
echo `date` >> $LOG_FILE
echo "Recent users to log in: " >> $LOG_FILE
last | head -10 >> $LOG_FILE
echo "Users who are currently online: " >> $LOG_FILE
who >> $LOG_FILE
}# no pine-debug[?]
alias pine='pine -d0'# special ls
alias ls='ls -aF --color' ~/.bash_logout
# .bash_logout
echo "You logged off at `date`"
echo "See you again `whoami`!"
sleep 2
clear
Let your imagination run wild. The shell is powerful enough to take in complex commands and functions. Examine the current configuration files you have on your system and tailor them to meet your specific needs.
CONCLUSION
Hopefully this tutorial has been able to guide you into making your ownbash
configuration files, and modifying your current ones. You are also encouraged to read the manual page forbash
:man bash
for those of you who do not know. The best way to learn is to read the manual and of course, to experiment.
X_console