Difference Between .bashrc and .bash_profile

Sarath Pillai's picture
Difference between .bashrc and .bash_profile

Bash is the default shell on most Linux distributions, and is pretty powerful because it supports many programming features as well. For example, bash supports conditional statements like if and else, variables, case statements, loops and much more. In this article, we will try to explore two main configuration files used by bash shell when it is launched.

 

The reason why I decided to write about this is due to the confusion and doubts floating around regarding these two configuration files. Mainly because both can be used for similar purposes, so why two files instead of having one.

 

The configuration files I am talking about here is ".bashrc" and ".bash_profile". Both are located in the home directory of a user. Both these files are read by bash shell when it starts. Let us dig through and understand their primary differences.

 

Before we get into the configuration file use cases, let us understand different types of shell sessions that bash supports. The reason we are discussing about login types is because the behaviour of bash and the files it reads depends on the shell session type.

 

What is Interactive & Non Interactive Shell?

 

You can easily guess this one. A shell process whose file descriptor 0, 1 and 2 are pointing to the the terminal device (/dev/tty, or /dev/pts/0 etc) is an interactive shell. Yes I know that is a tricky line to understand if you are new to Unix/Linux.

Let me put it this way. A shell where you can type commands(STDIN indicated by file descriptor 0) and see output (STDOUT indicated by file descriptor 1)and errors (STDERR indicated by 2) can be considered as an interactive shell.

Non interactive shells are basically shells launched by other programs. For example, cron. Or scripts that starts with SHEBANG (shebang is #!/bin/bash. The first line that majority of the scripts have in common).

 

What is login shell in Bash?

 

When you ssh to a remote server, the ssh program actually triggers the login program (which will intern read /etc/login.defs file and verifies password, shell name, home directory and things that are inside /etc/passwd file). After the authentication succeeds, ssh program will then trigger the shell program as shown below.

 

Related: Working of SSH Explained

 

execve("/bin/bash", ["-bash"])

 

 

execve is a system call to start a process with a program inside. I found this by using strace command to trace system calls that happened during a the login process.

 

If you are new to system calls and execve, the below articles might be helpful.

Read:  System Calls in Linux

Read: Creation of Processes in Linux using Execve

 

The most important thing to note here is "-bash" in execve. Why hyphen?. Why not simply "bash"?. This is because traditionally any program that triggered shell, used a method of prepending dash/hyphen ("-") to indicate it as a login shell. Many shells consider this as a signal to understand whether it is a login shell or not.  You can confirm this behavior of ssh by looking at the source code as well.

 

See the line number 1637 here: https://github.com/openssh/openssh-portable/blob/master/session.c

 

The bash man page confirms this.. See the snippet i took from bash man page below(ie: man bash).

 

INVOCATION
       A login shell is one whose first character of argument zero is a -, or one started with the --login option.

 

Another simple method to confirm whether you are in a login shell is to execute the below echo command (which will show the 0th argument of the running process). It will show the bash command that was used to start the shell. See the hyphen in the output below.

 

ubuntu@localhost:~$ echo $0
-bash

 

Read the man page snippet shown earlier carefully. It also states that bash will behave as a login shell if it is started with --login option as well (in which case you wont see hyphen prepended. Either of the two.).

 

Now let us see what bash does when it is triggered as a login shell (interactive or non-interactive). In other words, either while logging in using ssh or a terminal, or if you execute bash from an already existing shell with --login parameter.   It does the following.

 

  1. First it tries to read /etc/profile file (if it does not exist, it proceeds to the below. If it exist, then it will execute it and then proceed to below mentioned items)
  2. It searches for a file named ~/.bash_profile (ie: under the home directory of the user a file named .bash_profile. If it finds that file, it is executed and then does not look for anything mentioned below.)
  3. If ~/.bash_profile is not present, it will look for another file named ~/.bash_login (again inside the home directory of the user, and if it finds it, it is executed and then does not look for anything mentioned below.)
  4. If .bash_profile and .bash_login files are absent inside the home directory, then it will look for a file named .profile (again inside the home directory of the user). This .profile is actually read by almost all shells (ie: shells other than bash as well)

 

The main thing to note from what we understood till now is the fact that if bash shell is started as a login shell(irrespective of whether it is interactive or non-interactive), then it does not read .bashrc file. It only reads .bash_profile file. Let us now see when .bashrc comes into picture.

 

When does Bash read .bashrc file ?

When bash shell is started as a non login shell in interactive mode, then it reads .bashrc. The best example is when you execute the command bash.

Well the actual flow of configuration lookup is below.

 

  1. It first searches for a file named /etc/bash.bashrc, if this file exist, then it executes it and proceed to the below
  2. It searches for a file named .bashrc (under the home directory of the user), and if found, it executes it.

 

Should i use .bash_profile or .bashrc? Why two different files?

 

Two different files because they serve different purposes. Things that are specific to your login session should go inside .bash_profile. Things that is specific to bash shell itself should go to .bashrc.

Let us consider an example. Imagine a situation where you want some event to happen when somebody logs in. May be send an API call/e-mail alert with user details and other system statistics as soon as the user logs in. 

If you add such logic inside .bashrc, it will unnecessarily trigger that event, even if the user launches a new terminal (which is not a login). So it is better to add such things inside .bash_profile rather than .bashrc.

The best approach is to put things that is common to bash inside .bashrc, and then put the below content inside .bash_profile towards the end.

 

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

 

This way a login shell will always call .bashrc (and get bash specific configs as well), after executing login specific/session specific things from .bash_profile. In fact some distributions already does this.

Rate this article: 
Average: 5 (10 votes)

Add new comment

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
CAPTCHA
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.