Skip to content

Instantly share code, notes, and snippets.

@macmladen
Last active September 13, 2016 07:35
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save macmladen/7d28dadf9f1d5b958123 to your computer and use it in GitHub Desktop.
Save macmladen/7d28dadf9f1d5b958123 to your computer and use it in GitHub Desktop.
Linux and Mac interactive shell script loading

Order of script loading for interactive login shell

User can have multiple ways to login and different OSes, different shells have different approach. As I always search for same information, I decided to collect them here.

To understand what's going on here, you need to understand a little background information about how shells (bash in this case) are run.

  • When you open a terminal emulator (gnome-terminal for example), you are executing what is known as an interactive, non-login shell.
  • When you log into your machine from the command line, via ssh, or run a command such as su username, you are running an interactive login shell.
  • When you log in graphically, you are running something completely different, the details will depend on your system and graphical environment but in general it is the graphical shell that deals with your login. While many graphical shells (including the Ubuntu default) will read /etc/profile not all of them do.
  • Finally, when you run a shell script, it is run in a non-interactive, non-login shell.

Now, the files that bash will read when launched depend on the type of shell it is running as. The following is an excerpt of the INVOCATION section of man bash (emphasis mine):

When bash is invoked as an interactive login shell, or as a non-inter‐ active 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.

What all this means is that you are editing the wrong file. You can test this by dropping to a virtual console using Ctrl+Alt+F2 (return to the GUI with Alt+F7, or F8 depending on your setup) and logging in there. You will see that your prompt and aliases are available.

So, in order to have the setting you want applied to non-login shells, the type you get each time you open a terminal, you should make your changes to ~/.bashrc instead. Alternatively, you can also place your aliases in the file ~/.bash_aliases (however, note that this is an Ubuntu feature and you should not expect it to work on other distributions).

For more details on which file should be used for what, see here.

NOTES:

  • Debian (and by extension Ubuntu) also has the default ~/.profile source ~/.bashrc. This means that any changes you make to ~/.bashrc will also be inherited by login shells but
    • this is not the case in all Linux/Unix machines and
    • the inverse is not true which is why you should generally always work with ~/.bashrc & co rather than ~/.profile or /etc/profile.
  • Also, a general note on usage, changes made to the configuration files in /etc will affect all users. This is usually not what you want to do and should be avoided. You should always use the equivalent files in your home directory (~/).
  • The various configuration files are read sequentially. Specifically, for login shells, the order is:

/etc/profile -> /etc/profile.d/* (in alphabetical order) -> ~/.profile

This means that any setting in ~/.profile will overwrite anything set in the previous files.

Nice reading on Sitepoint

Mostly it is up to Linux/bash standards.

The remark is that .bashrc is intended for non-login shells and non-interactive should not read anything.

Also .bashrc should not produce any output as it may break apps like scp and rcp which source it.

In summary: login shells read files like profile, non-login shells read ~/.bashrc, and you should fix Terminal.app.

For more details on OS X terminal scripts, see on Apple Developer and Hayne

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment