Bash configuration

bike9876@エボ猫.コム

(From https://www.gnu.org/software/bash/manual/bash.html#What-is-Bash_003f) Bash is the shell, or command language interpreter, for the GNU operating system.

Generally one sets up 2 startup files to initialize things: ~/.bashrc and ~/.bash_profile 1, as described in the following sections.

Which files are used depends on whether bash is invoked as an interactive shell or not, and whether it is invoked as a login shell or not.

See https://www.gnu.org/software/bash/manual/bash.html#index-login-shell, but basically an interactive shell is one where you see a prompt and you can type commands. A non-interactive shell is when bash is used to run a script, eg bash foo.sh. If you use ssh to log in to a system, the same rules apply. So ssh <remote-system-name> would give an interactive shell, ssh <remote-system-name> ls would not.

A login shell is what you get when you first log into a system (eg via ssh or if you have a non-graphical environment and log in via a linux virtual console). Or you can fire up a login shell with bash --login. Starting up a new session or window with tmux fires up a login shell by default. By default, the gnome console program kgx does not start up shells as login shells. It can be configured to with

gsettings set org.gnome.Console shell "['/bin/bash','--login']"

(reset back to the default with gsettings reset org.gnome.Console shell).

The above login shells are all interactive, but running eg bash --login foo.sh would run foo.sh under a non-interactive login shell.

If you have gdm/wayland, gdm starts up a non-interactive login shell during user login (it runs bash -c 'exec /usr/bin/gnome-session --no-reexec' 2) Any programs later started in the gdm session will inherit any environment variables exported during that login shell execution.

~/.bashrc

~/.bashrc is read and executed when bash runs as an interactive shell that is not a login shell. In my setup, it will also be read and executed for an interactive login shell (see ~/.bash_profile below), so in my setup ~/.bashrc is used for all interactive shells and not for non-interactive shells. 3

So .bashrc is used to perform actions that are needed only for interactive shells. Aliases must also be set up in .bashrc (as they can’t be exported, so each shell instance needs to have them defined). Special shell variables like HISTSIZE and PS1 need to be set up in .bashrc.

For all users including root, I have ~/.bashrc with contents:


# ~/.bashrc

# If not running interactively, don't do anything
[[ $- != *i* ]] && return

for f in ~/local/bashrc.d/*; do [[ -r $f ]] && . $f; done; unset f

with further initialization done in files under ~/local/bashrc.d/.

Eg I have files:


# ~/local/bashrc.d/010bash_history_configure

# don't put duplicate lines or lines starting with space in the history.
HISTCONTROL=ignoreboth

# append to the history file, don't overwrite it
shopt -s histappend

# The maximum number of commands to remember on the history list
HISTSIZE=10000
# The maximum number of lines contained in the history file.
HISTFILESIZE=20000

# ~/local/bashrc.d/020disable_xon_xoff

# Ctrl-s/Ctrl-q turn off/on flow control (https://en.wikipedia.org/wiki/Software_flow_control)
# No need for this, and Ctrl-s is useful in bash history to search forwards from the current point in history
# (https://www.gnu.org/software/bash/manual/bash.html)

# Disable XON/XOFF flow control
stty -ixon

# ~/local/bashrc.d/030aliases

if [ -f ~/.bash_aliases ]; then
    . ~/.bash_aliases
fi

# ~/local/bashrc.d/040prompt

PS1='[\u@\h \W]\$ '

# Based on https://tldp.org/HOWTO/Bash-Prompt-HOWTO/xterm-title-bar-manipulations.html
# but using "modern" codes for start- and -end of escape sequence.
# Set the xterm titlebar with <user>@<host>: <cwd>
case $TERM in
    xterm*)
        PS1='\[\e]0;\u@\h: \W\a\]'"$PS1"
        ;;
esac

# ~/local/bashrc.d/050ls_color

# enable color support for ls 
if [ -x /usr/bin/dircolors ]; then
    test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
    alias ls='ls --color=auto'
fi

(I name files in ~/local/bashrc.d/ with a leading 0 if I want them to also be used by root (which is all of the above), see below.)

.bash_aliases

I define aliases in ~/.bash_aliases (and they are read in by ~/local/bashrc.d/030aliases above). Some examples I use:


# `~/.bash_aliases`

# tmux
alias tml='tmux ls'
alias tmn='tmux new'

I do not have a .bash_aliases for root.

.bash_profile

~/.bash_profile is read in and executed by login shells (interactive and non-interactive). This is done after /etc/profile is read in and executed.

Typically .bash_profile is used to set up and export shell environment variables (that are expected to keep the same values throughout the whole session).

For all users including root, I have ~/.bash_profile with contents:


# ~/.bash_profile

[[ -f ~/.bashrc ]] && . ~/.bashrc

for f in ~/local/profile.d/*; do [[ -r $f ]] && . $f; done; unset f

(as noted with .bashrc above, this means that ~/.bashrc is read in and executed for login shells).

Further initialization is done in files under ~/local/profile.d/.

Eg I have files:


# ~/local/profile.d/100add_dot_local_bin_to_path

# Add ~/.local/bin to PATH if directory exists and it isn't in PATH already
if [ -d "$HOME/.local/bin" ]; then
    (echo $PATH | grep -qE '(^|:)'$HOME'/\.local/bin(:|$)') || PATH="$HOME/.local/bin:$PATH"
fi

# ~/local/profile.d/110add_bin_to_path

# Add ~/bin to PATH if directory exists and it isn't in PATH already
if [ -d "$HOME/bin" ]; then
    (echo $PATH | grep -qE '(^|:)'$HOME'/bin(:|$)') || PATH="$HOME/bin:$PATH"
fi

I do not use these ~/local/profile.d/ files for the root user (and so do not have a leading 0 in the filename [cf ~/local/bashrc.d/ files above]).


  1. The startup files /etc/profile, ~/.bash_login, ~/.profile, ~/.bash_logout, and any file as the value of $BASH_ENV are also used, but not described here (see https://www.gnu.org/software/bash/manual/bash.html#Bash-Startup-Files).↩︎

  2. gdm runs bash -c 'exec /usr/bin/gnome-session --no-reexec' but sets $0="-bash" so bash will be run as a login shell (see https://www.gnu.org/software/bash/manual/bash.html#index-login-shell).↩︎

  3. To be precise, my (and the default Arch Linux) ~/.bashrc is executed for non-interactive login shells, but the first thing it does is exit if running non-interactively.↩︎