Field Guide to Bash Terminals

Shell Linux

You’re setting up your bash profile. You go to the Bash man page. Damn… you just wanted to know where to stick your config and aliases and this page is written in legalese!

This is an overview of the different kinds of Bash terminal and how they find their config, written in less detail but more to the point.

Terminology used:

The 2 File Chains

These file chains are referred to later on and act as a shorthand for particular behaviours of Bash. ‘File chain’ isn’t an official term, I made it up for this post.

Some general notes:

profile file chain - run once per login
bashrc file chain - run once per terminal creation

/etc/bash.bashrc was added so that the bashrc file chain would have its own location for system-wide configuration, like /etc/profile provides. Debian and Ubuntu have adopted this feature.

The 5 Different Kinds of Terminal

--login --interactive

e.g. SSH-ing somewhere, or logging into your physical computer

Runs the profile file chain, as this will be the first terminal to run for a user on a system. When terminals create other terminals, they pass on their environment variables to their children, which is how the profile file chain is shared among all terminals on a system.

Although it is interactive, the property of being a login terminal overrides being an interactive terminal, so a login terminal won’t run the bashrc file chain by default.

It’s useful to make the assumption that login terminals are always interactive - they usually are, and it allows us to:

There’s an edge case that contradicts this rule that I’ll cover later.

--interactive

e.g. bash, or opening a GUI terminal program

Runs the bashrc file chain. Doesn’t run profile file chain as it expects to inherit it from a parent login terminal. bashrc file chain is run once per terminal because:

-c locally

e.g. bash -c 'echo hello world'

Run Bash with a single command rather than interactively. Expects to inherit both the profile and bashrc file chains from a parent terminal. It also has a special environment variable, $BASH_ENV, which can be set to a file path. Bash will run all commands in that file, before running the command set with -c

-c remotely

e.g. ssh user@host 'echo hello world'

Although it doesn’t actually use the -c syntax, ssh user@host <command> achieves a similar effect. It won’t run the remote profile file chain, unlike SSH-ing normally does and it doesn’t use the $BASH_ENV variable, but it will still run the remote system’s bashrc file chain before running the command.

--login, non-interactively?? The Edge Case

e.g. ssh user@host < input-file.txt

99.99% of the time you can assume that all login terminals are also interactive. 0.01% of the time you “need” to pipe a command in a local file to be run on a remote system. In this edge case, the remote profile file chain will be run, then the contents of input-file.txt, and then the SSH connection will terminate. This edge case won’t even have any meaningful side-effects most of the time.

Key Points