Bash Logo

The Bourne-again shell (or bash), based on the Bourne shell (sh) but owes some of its allegiance to the Korn shell (ksh), which tried to combine the features of the C Shell (csh) and Bourne shell. They’re not clones of each other, but do have some things in common. Not complicated at all.

It seems variable where to put the variables

You have a variable that you need to set when you start your system. This might be because you have a window tiling manager that needs something specific, you’re rolling your own system, or an installation document states you need to set it. The trouble is, there are lots of places mentioned on various internet forums and reddit and everywhere else where this can be done.

Some mention your home’s .profile while others mention .bashrc or even /etc/environment and it can be confusing where you should set a variable. Sometimes you might follow a guide and the variable doesn’t get set. What is going on?

There is an order to everything

When you first log in, various scripts get executed by the shell. Initially a non-interactive login shell will start (you can’t type into it or view what it outputs). This first type will do the heavy lifting to start with.

If you log in to the tty, or open a terminal window, you will be given an interactive shell. An actual usable, as far as you’re concerned, type of shell. This you can type into and do things with, such as enter commands like ls or cd into directories, or play a game of nethack!

The two types of shells execute scripts that set things like your prompt, your aliases, colours for ls, your configuration folder location like XDG_CONFIG_HOME and other amazing things so that the shell will be usable. There is an order to these things and some files may override others, or variables set in one may be set again somewhere else. Confusing, but let’s break down what the shell executes.

Resource files

This guide is based on Bash (hence the title), but other shells also execute resource files in a certain order. It’s best to check the documentation for the shell to find out what order that is.

Firstly the /etc/environment file is read - this is top level and not user, session or shell specific. This is used to set variables and is not executed. This is important because the information can only be name=value and not much else. It’s also important not to put anything in here that may be different depending on the session or user. For example, putting wayland specific variables here would be nonsense when an X11 session could be run.

It is also worth noting that the variables can not use variable expansion, such as including a previously defined variable in the assignment.

Non-Interactive Shell

The Display Manager or tty, once the user is authenticated and logged in, will run a non-interactive shell and execute the following scripts:

  • /etc/profile if it exists and anything named *.sh or sh.local in /etc/profile.d (executed from within /etc/profile)
  • Then will run (in this order)
    • $HOME/.bash_profile if it exists OR
    • $HOME/.bash_login if it exists OR
    • $HOME/.profile if it exists. Normally $HOME/.bashrc is executed from $HOME/.profile too, if it’s there, when using the bash shell.

This order is important. If you have a .bash_profile file in your home directory and you put environment variables in a .profile file, they’ll never be set because .profile will never be executed.

Interactive Shell

Interactive shells will run:

  • /etc/bashrc if it exists and anything named *.sh in /etc/profile.d (executed from within /etc/bashrc)
  • $HOME/.bashrc

Variables for bash, just for the user

Hopefully this shows that where you put the variables is important, depending on at what point you want those visible to the system. A sane default for most distros is to only have a .profile and .bashrc file in your home directory. The .profile will normally contain a section that checks for and executes .bashrc if it exists. If this is the case, then putting variables you want to set in .bashrc is a safe bet for interactive and non-interactive shells.

Variables for bash, system wide

It’s also important to note that although /etc/profile should be read on every distro, you might need to look inside it to work out what else this in turn executes. This will give you an idea where executed scripts are located.

/etc/profile or, if used, a script created in /etc/profile.d are excellent places to put system wide, but bash specific variables. The extension is important, as noted above, only *.sh files will be executed in /etc/profile.d for bash.