Page Body

The Bash Shell Environment

A shell is a command line interpreter that provides a user interface for terminal windows. This interface encloses the operating system it is running on, like a shell, and hides the operating system from view. Graphical desktops, like GNOME, are also shells, but instead of reading text commands from the keyboard, they read graphical commands via a mouse or trackpad.

The Bourne or Bourne-like shells are the:

  • Bourne Shell (sh)
  • Bourne-Again Shell (bash)
  • Korn Shell (ksh)
  • Z Shell (zsh)

The C or C-Shell-like shells are the:

  • C Shell (csh)
  • Tenex C shell (tcsh)

Note: If you are not familiar with the GNU/Linux command line interface, review the Conventions page before proceeding.

The Bash Shell

The Bash shell (the Bourne-Again shell) is the default shell for many GNU/Linux distributions. It was designed as a free alternative to UNIX's Bourne shell.

bash represents the return of the traditionally C-shell-using BSD world to the Bourne concepts.

Shell Command Format

The format for a shell command is:

command options arguments

For example, you can determine which shell you are currently using by running the echo "${SHELL}" command, which outputs the contents of the SHELL environment variable.

Options are switches that turn specific aspects of a command on or off. Most options start with a dash (-) and can be aggregated behind a single dash (e.g., -abc). Long options start with two dashes (--) and cannot be aggregated.

Arguments are the values that commands act on. Options can have their own arguments, as well.

For some commands (e.g., tar, paste), a - by itself can be used to represent the standard output or standard input as an argument. A -- by itself, without any options, instructs a command to expect a filename, rather than an option (i.e., it represents the end of options).

Internal and External Commands

Internal commands are made available to the shell itself and are built-in commands. These commands can be viewed with the help command. The type command, which tells you how a command will be interpreted by the shell, will tell if you a command is a built-in command (an alternative to type is the command -V command).

External commands are executable files that exist outside of the shell within the file system.

Shell Variables

Shell variables govern various aspects of a shell's behavior. In a shell, a variable consists of a name and a value. A variable's name consists of a sequence of letters, digits, and underscores (_), and must start with a letter or underscore.

The shell does not require variables to be declared before use. When you assign a value to a variable that has not been used before, it springs into existence:

ex_variable_name=ex_variable_value

Make sure that there are no spaces around the assignment operator (=).

To use a variable on the command line and have its name substituted for its value, you can surround the variable name with curly braces ({}) and prefix it with a dollar sign ($).

echo ${ex_variable}

All variables are shell variables, and some shell variables are also environment variables, like SHELL. Environment variables govern aspects of child processes (e.g., programs started from the shell, including other shells), as well as those of the parent shell itself.

Environment variables are copied to (i.e., available to) child processes, whereas regular shell variables are not. By convention, internal shell variable and environment variable names are capitalized.

Shell Aliases

Shell aliases are custom strings that are used as shortcuts for a command or series of commands. Often, they are used to:

  • Replace a complicated command or sequence of commands with an easily remembered string
  • Redefine a command to use a specific set of command options
  • Automatically correct common command typos

Aliases are created with the built-in alias command:

alias ex_alias_name=ex_command

For example, this alias redefines the man command to always show all of the manual pages with names that match the provided name:

alias man='man -a'

All aliases can be viewed or removed by entering alias and unalias, respectively.

A specific alias or set of aliases can be removed like so:

unalias ex_alias_name...

Aliases have several special properties:

  • They take priority over commands found in the shell environment's PATH, which is why they can be used to redefine extant commands. To temporarily negate an alias, escape it with a backslash (e.g., \ex_alias_name) or use the absolute path to the command in question.
  • They are stored in the shell's memory, so they are only accessible to the current shell (i.e., other programs and child processes of the same shell cannot access them).
  • They are executed by the current shell and do not require the creation of a new process.
  • They cannot have local variables or process arguments.

Shell Functions

Shell functions are blocks of code that can be repeatedly called by invoking the name of the function. Functions are created as follows:

ex_function_name() {
    ex_commands
}

For example, this simple function outputs a greeting:

hello_world() {
    echo 'Hello, world!'
}

The function is called by using its name, hello_world.

Functions share the same special properties outlined for aliases above, with the exception that they support local variables and the processing of arguments.

Shell Options

Shell options are settings you can toggle to change the shell's behavior. For example, there are shell options that can help you debug shell scripts, and to enable/disable shell features like brace expansion and filename expansion.

Command Precedence

The order of precedence for commands when entered at the command line is:

  1. Aliases
  2. Keywords (e.g., if, for)
  3. Functions
  4. Internal commands (e.g., cd, type)
  5. Scripts and external commands

Keeping this rule in mind will help you understand what to expect when you execute commands on your shell.

Shell Types

There are three forms of shells:

  1. Login shells
  2. Interactive shells
  3. Non-interactive shells

Login Shells

The login shell is the shell that you immediately obtain after logging into your system. The program that starts the login shell passes the shell a - as the first character of its program name. You can use this fact to determine if your current shell is a login shell.

For example, running echo "${0}" will display the value of the ${0} special variable, which contains the name of the shell (or shell script). If the first character you see is a -, your shell is a login shell.

You can determine your user's login shell by running the following command:

getent passwd ex_username | cut -d: -f7

getent passwd searches the /etc/passwd file for a user line that matches the username you specify. The output of that command is sent to the cut command via a pipeline. cut -d: -f7 returns the 7th field in the colon-delimited line for the specified user account from /etc/passwd. That field contains your user's login shell.

You can view the login shells available on your system by running the ls $(cat /etc/shells) 2> '/dev/null' command. If a shell listed in /etc/shells is not installed on your system, the ls command will generate an error for that entry, and that error will be suppressed by being redirected to /dev/null, i.e., a bit bucket (comment lines in /etc/shells will be suppressed, too).

If you are not using a restricted login shell, you can change the login shell for your account with the chsh -s command:

chsh -s /full/path/to/example/shell

Running the chsh command by itself will start it in interactive mode, where you will need to provide the full path to your new login shell. Unless you are using this command as the root user, the shell you specify must be listed in /etc/shells.

If you are acting as root, you can change the login shell for any user account:

# chsh -s /full/path/to/example/shell ex_username

You can open a login shell for a user account by using sudo -i or su -l:

  • sudo -i ex_username
  • su -l ex_username

If you do not specify a username, the root user (superuser) is assumed.

You can open a non-login shell for a user account by using sudo -s or su:

  • sudo -s ex_username
  • su ex_username

Again, if you do not specify a username, the root user (superuser) is assumed.

Interactive Shells

If you use bash without any arguments, and its standard input and standard output channels are connected to a terminal, it will see itself as an interactive shell. If you are using a GNU/Linux system with a graphical environment, the terminal emulators that you open on your desktop are interactive shells.

Non-Interactive Shells

Non-interactive shells are shells that do not process any files when started or terminated. A shell is non-interactive if it is used to execute a shell script, or if a program uses a shell to run another program.

The Shell Environment

Your shell has an environment, i.e., a variety of variables, aliases, functions, and options that are available to it. This environment is established by executing commands from various files in a specific order, based on the kind of shell that you are using.

Commands from a file can be loaded into a shell's environment using the source or . commands (e.g., . /path/to/example/file).

The Login Shell Environment

For login shells, the file sourcing order is (where ~ represents the user's home directory):

  1. /etc/profile
  2. /etc/profile.d/ files
  3. ~/.bash_profile or ~/.bash_login or ~/.profile
  4. ~/.bashrc
  5. ~/.bash_logout (upon quitting a login shell, and only if the file exists)

The Non-Login Shell Environment

For non-login shells, the file sourcing order is:

  1. /etc/bash.bashrc or /etc/bashrc (which file is used depends on your GNU/Linux distribution)
  2. ~/.bashrc

When you quit an interactive non-login shell, no files are processed.

Shell Environment Configuration

Settings that apply to all system users can be placed into /etc/profile, and either /etc/bash.bashrc or /etc/bashrc, depending on your GNU/Linux distribution. Child shells inherit a copy of the environment established by these files.

Settings specific to your user account can go in your user-specific files. Generally, environment variables (e.g., PATH, SHELL) are set once, so it is sufficient to define them in either ~/.bash_profile, ~/.bash_login, or ~/.profile.

Shell variables that are not environment variables and customize the shell's behavior (e.g., HISTSIZE, PS1), and shell options, are good candidates for being placed in your ~/.bashrc file. Aliases and functions can go here, too.

To have these user-specific items available in login shells, you can have your login shell configuration file (i.e., ~/.bash_profile or ~/.bash_login or ~/.profile) source your ~/.bashrc file.

Shell Environment Commands

There are several commands that will show you your shell's environment:

set or declare
Display all shell variables and functions.
env or printenv or export
Display all environment variables.

set

You can set and unset shell options with the eponymous set command. To set a shell option, you use the -o option:

set -o ex_option

To unset a shell option, you use the +o option:

set +o ex_option

set can also be used to set Bash's positional parameters:

$ set a b c d
$ echo "${2}"
b

declare

By itself, the declare command displays the attributes and values of all variables. When provided a variable name, it can also be used to set variable values and attributes.

For example, you can declare an integer variable as follows:

declare -i ex_variable=ex_integer

To unset the integer attribute on the variable above, you can use the +i option:

declare +i ex_variable

If you want to see your environment's functions and their contents, you can use the declare -f command. If you only want to see the function names, use declare -F, instead.

When declare is used in a function, it makes variables local, unless you use the -g option.

shopt

The shopt command also allows you to set shell options. Here, the -s option is used to set a shell option, and the -u option is used to unset one.

You can view all the shell options that you can configure with the shopt command by entering shopt at the command line.

env

env -i ex_command (-i is short for --ignore-environment) lets you execute a current session command in an empty environment by temporarily clearing out all environment variables (outside of those you include with the command itself, e.g., env -i ex_variable ex_command).

A variable (or function) can be removed from the environment by using the unset command (read-only variables cannot be unset; run help readonly for more information):

unset ex_object

export

You can promote a shell variable into an environment variable with the previously mentioned export command:

export ex_variable...

Afterwards, child processes will be able to modify the value of the exported variable. However, the parent shell will not see the child processes' changes, i.e., exported variables are not shared, they are only copied and inherited. Unless your export command is placed in a shell environment configuration file, your change will not be permanent.

To convert a promoted variable back into a shell variable, you can use export's -n option.

Documentation

For more information on the topics discussed here, refer to the Linux User's Manual, either at the command line or online.

Enjoyed this post?

Subscribe to the feed for the latest updates.