The Bash Environment
- Machtelt Garrels. Chapter 3. The Bash environment. Bash Guide for Beginners.
- 蔡德明. 第十一章 认识与学习Bash. 鸟哥的Linux私房菜.
Intro
Commands and implementations may be specific for Ubuntu22.04, but the concepts should be universal for all Unix like systems.
Login shell and Interactive shell
-->Source
man bash
:A login shell is one whose first character of argument zero is a -, or one started with the --login option.
An interactive shell is one started without non-option arguments (unless -s is specified) and without the -c option whose standard input and error are both connected to terminals (as determined by isatty(3)), or one started with the -i option. PS1 is set and $- includes i if bash is interactive, allowing a shell script or a startup file to test this state.
- interactive shell: An interactive shell generally reads from, and writes to, a user's terminal: input and output are connected to a terminal.
- login shell: The shell executed with a login process is a login shell. For example, when you log into your machine through
tty1 ~ tty6
, or through, you need to input the username and password, that's a login process. So the started shell is a login shell.- interactive login shell: When you log into your machine from the command line, via
ssh
, or run a command such assu - username
, you are running an interactive login shell.
- interactive login shell: When you log into your machine from the command line, via
- non-login shell: The shell that doesn't executed with a login process is a non-login shell. For example, if you use a graphic interface, say X windows, then you've logged into the system using the the graphic interface, not the shell. You can start a non-login shell via a terminal emulator like
KDE Konsole
.- interactive, non-login shell: When you open a terminal emulator (
iTerm
for example), the executed shell is interactive, but not a login shell, meaning you didn't use it to login the system.
- interactive, non-login shell: When you open a terminal emulator (
- Finally, when you run a shell script, it is run in a non-interactive, non-login shell.
Is this shell interactive?
-->Source
Test by looking at the content of the special parameter -
, it contains an 'i' when the shell is interactive:
1 | > echo $- |
In non-interactive shells, the prompt, PS1
, is unset.
Is this shell a login shell?
-->Source
If bash is started by a login process (e.g. by /bin/login) the first argument by convention is prefixed with a - character:
1 | $ echo $0 |
Bash uses this to determine if the shell should be treated as a login shell. Bash then checks to see if the shell is interactive, this is done by calling isatty
to check stdin and stderr are connected to a tty. There are a few exceptions to this, for example using the -c
option will normally prevent bash running as an interactive shell. For more info on the other exceptions, refer to the bash docs.
- On OS X, a terminal (including iTerm) by default runs a login shell (Zsh) every time, so this argument not satisfies all systems.
Shell initialization files
man bash
:When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable. The --noprofile option may be used when the shell is started to inhibit this behavior.
When an interactive shell that is not a login shell is started, bash reads and executes commands from /etc/bash.bashrc and ~/.bashrc, if these files exist. This may be inhibited by using the --norc option. The --rcfile file option will force bash to read and execute commands from file instead of /etc/bash.bashrc and ~/.bashrc.
The shell initialization files can be split as two categories:
- System-wide configuration files
- Individual user configuration files
A configuration file in the root dir /
is system-wide, file in the home dir ~/
is user-wide.
According to the output of man bash
,
When an interactiv login shell is started, it'll:
- Read
/etc/profile
, which is system-wide. - Then it'll read (if any)
~/.bash_profile, ~/.bash_login, and ~/.profile
, which are user-wide.
When an interactive non-login shell is started, it'll:
- Read
/etc/bash.bashrc
, which is system-wide. - Then it'll read (if any)
~/.bashrc
, which is user-wide.
NOTE:
/etc/profile
is only read by login shells, and~/.bashrc
is only read by non-login shells.- The specific files depends on the platform. In Ubuntu22.04, there's no
~/.bash_profile, ~/.bash_login, and ~/.profile
, only a~/.bashrc
. In MacOS, there's only a~/.bash_profile
. In this chapter, all commands and files are contraint to Ubuntu22.04. - The system will skip config files if they're missing. You can create them manually as well.
System-wide configuration files
/etc/profile
Let's see it's content:
1 | In Ubuntu 22.04 |
Basically, /etc/profile
will do two things:
Search if file
/etc/bash.bashrc
exists, if it does, execute it.1
2
3if [ -f /etc/bash.bashrc ]; then
. /etc/bash.bashrc
fiSearch if dir
/etc/profile.d
exists, if it does, execute all the files (if readable) in it.
1
2
3
4
5
6
7
8if [ -d /etc/profile.d ]; then
for i in /etc/profile.d/*.sh; do
if [ -r $i ]; then
. $i
fi
done
unset i
fi
/etc/bash.bashrc
We can see the content of /etc/bash.bashrc
:
1 | System-wide .bashrc file for interactive bash(1) shells. |
/etc/profile.d
We can see the content of files in /etc/profile.d
:
1 | $ ls /etc/profile.d |
Every .sh
file is just a simple shell script.
User-wide configuration files
In Ubuntu22.04, there's no ~/.bash_profile, ~/.bash_login, and ~/.profile
, only a ~/.bashrc
.
~/.bashrc
The content of ~/.bashrc
:
1 | In Ubuntu 22.04 |
Zsh initialization files
--> Zsh manual
Zsh uses different config files from bash.
When an interactiv Zshl (Not clear if whether login affects) is started, it'll:
Read system-wide config files in the order
zshenv, zprofile, zshrc, zlogin
. See/etc/zsh.zshenv
:1
2
3
4
5
6
7
8
9
10
11
12
13
14# /etc/zsh/zshenv: system-wide .zshenv file for zsh(1).
#
# This file is sourced on all invocations of the shell.
# If the -f flag is present or if the NO_RCS option is
# set within this file, all other initialization files
# are skipped.
#
# This file should contain commands to set the command
# search path, plus other important environment variables.
# This file should not contain commands that produce
# output or assume the shell is attached to a tty.
#
# Global Order: zshenv, zprofile, zshrc, zlogin
# ....Read user-wide config file:
~/.zshrc