Bash Intro
Bash, short for Bourne Again Shell, is a widely-used command-line interpreter in Unix-based systems like Linux. It is one type of shell, specifically an enhanced version of the original Bourne Shell (sh). Bash offers advanced scripting capabilities and numerous features for executing commands and automating tasks. It is essential for system administrators and developers, facilitating automation of repetitive tasks, system configurations, and application deployments. With support for variables, control structures, and a vast array of commands, Bash provides a powerful and efficient way to manage and interact with the operating system. This makes it a critical tool for users in the Linux environment, enabling them to streamline processes and improve productivity.
Default Shell
Upon logging into a Unix system, a user is automatically provided with a shell as a default shell, which serves as their primary interface for executing commands and scripts. This default shell is specified in the /etc/passwd
file. Each line in this file corresponds to a user account and includes various details such as the username, user ID, group ID, home directory, and the default shell.
Here is an example snippet from the /etc/passwd
file:
[dmtsai@study ~]$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
.....(omitted).....
In this example, the last field in each line specifies the default shell. For instance, the root
user has /bin/bash
as their default shell, which is the Bash shell. On the other hand, system accounts like bin
and daemon
have /sbin/nologin
, which prevents these accounts from logging into an interactive shell.
The shell environment can be customized according to the user’s preferences. Users can also switch between different shells if needed. One of the critical aspects of shell usage is understanding and managing variables, which are fundamental in many programming languages and essential for efficient shell scripting.
Different Shells and Bash
So, how many shells are available for use on our Linux system (using CentOS 7.x as an example)? You can check the /etc/shells
file to see at least the following available shells (duplicate entries have been omitted, such as /bin/sh
being the same as /usr/bin/sh
):
/bin/sh
(has been replaced by/bin/bash
)/bin/bash
(the default shell for Linux)/bin/tcsh
(integrates C Shell and provides additional features)/bin/csh
(has been replaced by/bin/tcsh
)
Users can freely switch to their preferred shell, but different shells have varying usage and syntax. For example, Bash uses the syntax var='content'
for setting variables, whereas csh uses set var = 'content'
. In csh, set
is required, and spaces are allowed around the equals sign.
Shell in Mac
Bash shell was introduced to replace Bourne Shell(sh) and to become the default Linux shell. Bash is capable of performing a wide range of programming solutions and automated tasks. In Linux, several other shells can perform similar tasks as bash.
Zsh was created after the bash shell. It has various features that are also present in the Bash shell. However, some features make it superior to bash, such as Plugin support, Spelling correction, Themes bundle, CD automation, etc. If you are a Linux user, you do not have to install Zsh separately since it is included by default in the Bash shell.
Mac comes with a Unix shell that provides a command line interface. Since 2019, Apple replaces bash with zsh as the default shell in macOS Catalina.
You can use echo $0
to find the current shell is using in your Mac. You will see either bash
or zsh
in the terminal.
By default, the .zshrc
file does not exist for a standard user, even if you launch the zsh shell. This may come as some surprise, but since the .zshrc
file is used to configure the zsh shell, you’ll need to manually create one in your home directory for zsh to access. There’s also a system-level zshrc file, but that is less commonly modified by users.
Do note that if you install Oh My Zsh, a .zshrc
file will be created automatically for you.
Bash Environment Config Files
Have you ever wondered why you get a bunch of useful variables when you start Bash without doing anything? This is because the system has some environment configuration files that Bash reads upon startup to set up the operating environment. These configuration files can be categorized into system-wide settings and user-specific preferences. Note that command aliases and custom variables discussed in previous sections will be lost when you log out of Bash, so you need to write these settings into configuration files to retain them. Let's delve into these!
Login and Non-login Shell
Before introducing Bash configuration files, we need to understand login and non-login shells. The key difference is whether you have to log in.
- Login shell: This requires a complete login process to obtain Bash. For example, logging in from tty1 to tty6, where you need to enter your username and password, results in a login shell.
- Non-login shell: This does not require a repeated login process. For example, after logging into Linux via X window and opening a terminal in the graphical interface, you don't need to re-enter your username and password; this is a non-login shell. Similarly, running the
bash
command within an existing Bash session starts a non-login shell.
Why introduce login and non-login shells? Because they read different configuration files. Since logging into the system usually involves a login shell, let's first discuss which configuration files it reads. Typically, a login shell reads only these two configuration files:
- /etc/profile: This is the system-wide configuration file; it's best not to modify this file.
- ~/.bash_profile, ~/.bash_login, or ~/.profile: These are user-specific configuration files. Modify these to change your personal settings.
/etc/profile
You can use vim
to read this file's contents. This configuration file uses the user ID (UID) to determine many important variable settings, and it's read whenever a user logs into Bash. If you want to set the environment for all users, modify this file—but it's better not to change it unnecessarily. Key variables set in this file include:
- PATH: Determines if the sbin directories are included based on the UID.
- MAIL: Sets the user's mailbox to
/var/spool/mail/username
based on the account. - USER: Sets this variable based on the username.
- HOSTNAME: Sets this variable based on the hostname command.
- HISTSIZE: Number of command history records, set to 1000 in CentOS 7.x.
- umask: Default file permission settings, 022 for root and 002 for regular users.
~/.bash_profile
After reading the system-wide /etc/profile
and possibly calling other configuration files, Bash reads the user's personal configuration file. In a login shell, Bash primarily reads one of these three files in this order:
- ~/.bash_profile
- ~/.bash_login
- ~/.profile
Bash reads only one of these files, in the order listed above. If ~/.bash_profile
exists, the other two are not read. If ~/.bash_profile
doesn't exist, it reads ~/.bash_login
, and if that doesn't exist, it reads ~/.profile
. The multiple files exist to accommodate users transitioning from other shells. Here is an example of ~/.bash_profile
:
[dmtsai@study ~]$ cat ~/.bash_profile
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then # These lines check for and read ~/.bashrc
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/.local/bin:$HOME/bin # These lines handle personalized settings
export PATH
Here’s the reading process for the login shell:
$PATH
is a critical environment variable in Unix-like operating systems (including macOS, Linux, and others) and in Windows. It defines a list of directories that the system searches to find executable files when you enter a command in the command-line interface (CLI).
Bash & Zsh lading sequence
If you are using Mac, you may use zshrc
instead of bashrc
, the functionality is the same. It's just one for zsh and the other one for bash.
- Bash
- ZSH
/bin/bash
: The bash executable/etc/profile
: The systemwide initialization file, executed for login shells~/.bash_profile
: The personal initialization file, executed for login shells~/.bashrc
: The individual per-interactive-shell startup file. In zsh,~/.zshrc
file does the same thing.~/.bash_logout
: The individual login shell cleanup file, executed when a login shell exits~/.inputrc
: Individual readline initialization file
Source: Zsh/Bash startup files loading order (.bashrc, .zshrc etc.)
Note that zsh seems to read ~/.profile as well, if ~/.zshrc is not present.
Interactive Login | Interactive non-login | Script | |
---|---|---|---|
/etc/zshenv | A | A | A |
~/.zshenv | B | B | B |
/etc/zprofile | C | ||
~/.zprofile | D | ||
/etc/zshrc | E | ||
~/.zshrc | F | C | |
/etc/zlogin | G | D | |
~/.zlogin | H | ||
~/.zlogout | I | ||
/etc/zlogout | J |
source
TL;DR - read the configuration files directly without logging out and back in
In Linux, the source
command (or its shorthand .
) is used to execute commands from a file in the current shell session. This means it runs the script without creating a new subshell, allowing the script to modify the environment variables of the current shell.
For example, if you modify ~/.bashrc
, you can immediately apply the new settings to the current environment by running source ~/.bashrc
without logging out. This is very convenient! The settings in ~/.bash_profile
and /etc/profile
often also use the source
(or dot) command.
$ source <configuration-file>
# Example: Read the ~/.bashrc settings into the current bash environment
$ source ~/.bashrc # The following two commands are equivalent!
$ . ~/.bashrc