Overview#Bash, and most other shells, can be started as a login shell or as a non-login shell. One of the most significant differences between the two modes is the Shell Initialization Files executed when Bash starts up.
Terminology#First, we need to get the terminology right, or at least we need to agree on the terminology we are using here. These are our explanations as we understand them:
login shell#A login shell is one whose first character of argument zero is a -, or one started with the --login option. You can determine if the shell is a login shell by:
echo $0 -bashSince "-bash" has the first character is "-", this is a login shell. When a login shell exits, bash reads and executes commands from the file [~/.bash_logout], if it exists.
non-login shell#A login shell is one whose first character of argument zero is NOT an -.
interactive shell#An interactive shell is one started without non-option arguments 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.
The interactive shell is used when you open a terminal session.
You can determine if the shell is interactive if the variable "-" includes an "i".
echo $- himBHAs "himBH" includes the character "i", this is an interactive shell.
Typically the environment variable PS1 (the primary prompt string) is set when using an interactive shell.
A interactive login shell is exited by 'logout'. Typing 'exit' in a login shell will run 'logout'.
To prevent bash from running the interactive login shell scripts when it is invoked as an interactive login shell you can use the option:
non-interactive shell#When bash is started non-interactively, to run a shell script for example, it looks for the variable BASH_ENV in the environment, expands its value if it appears there, and uses the expanded value as the name of a file to read and execute.
When you run a shell script, a new non-interactive shell is launched to execute the script. The new shell is a non-interactive shell.
You can determine if the shell is interactive if the variable "-" does NOT includes an "i".
echo $- hB
A non-interactive shell is exited by 'exit'
To prevent bash from running the non-interactive shell scripts when it is invoked as a interactive login shell you can use the:
Order of Execution#Login shells, regardless of if they are interactive or non-interactive read and execute the .profile
Interactive shells also read and execute .bashrc.
The order of execution of the initialization scripts for a shell is dependent on if the shell is interactive or non-interactive and not related to if it is a login script or not.
When bash is invoked as an interactive login shell it reads and executes commands from the [/etc/profile]. Then Bash will then try in order to execute ONLY the first file exists and is readable of the following:
This same process is followed when a non-interactive login shell is invoked with the --login option.
Best Practices#The best method then is to:
- Do not modify [etc/profile] file
- .bashrc - Put ONLY ENV etting that do NOT interact with the session.
- .bash_profile - Put any changes in here that you would like. They will only be executed in interactive shells (like terminal sessions)
- Test with is your shell clean method.
Where to put what#The key to remember is that all of the shells will execute the [/etc/bashrc] and [~/.bashrc files]. Generally no settings in the [/etc/bashrc] and [~/.bashrc] files should interact with the console.
This implies none of the following:
- prompt settings
- color changes or highlighting
ssh remotesystem ../bin/true > test.datThis should create a file called test.dat with nothing in it. If test.dat is not of zero length then your shell is not clean. Look at the contents of test.dat to see what was sent. Look at all the shell initialization files on remotesystem to try and find the problem.
My MAC (OS X 10.6.6)#
More Information#There might be more information for this subject on one of the following:
- [#1] - Understanding a little more about /etc/profile and /etc/bashrc - based on information obtained 2014-04-03