~/.bashrc VS ~/.profile VS ~/.bash_profile

Introduction

Sometimes, when I remotely login to some Linux computers or use Docker containers, I would find the shell is plain black and white, different from the colorful shell I am used to dealing with on my local machine. This sometimes makes it difficult to look for libraries, executables, and folders. Sometimes, some executables could be called directly from a local shell but from a remote login shell they are not directly callable.

It turns out that the shell is an executable and it is “configured” by special shell scripts such as ~/.bashrc, ~/.profile, ~/.bash_profile. In this blog post, I would like to briefly discuss the differences between these scripts.

~/.bashrc

I modify the ~/.bashrc file from time to time, because sometimes I would like to set some environment variables, including PATH which is an environmental variable in Linux and other Unix-like operating systems that tells the shell which directories to search when looking for executable files. But I have been ignoring the commented block at its beginning for decades.

1
2
3
4
5
$ cat ~/.bashrc 
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples
...

This means that in a local shell where bash is being used, this shell script will be executed immediately after bash is executed. There are many other shell executable variants, such as zsh. ~/.bashrc is only specific to bash.

There are many settings in the ~/.bashrc that makes the shell look colorful. For example,

1
2
3
4
5
6
7
8
9
10
11
# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
alias ls='ls --color=auto'
#alias dir='dir --color=auto'
#alias vdir='vdir --color=auto'

alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
fi

~/.profile

The comment block found in the ~/.profile explicitly tells us that it will be executed for the login shells. However, if ~/.bash_profile or ~/.bash_login exists, ~/.profile will not be executed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$ cat ~/.profile 
# ~/.profile: executed by the command interpreter for login shells.
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
# exists.
# see /usr/share/doc/bash/examples/startup-files for examples.
# the files are located in the bash-doc package.

# the default umask is set in /etc/profile; for setting the umask
# for ssh logins, install and configure the libpam-umask package.
# umask 022

# if running bash
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
PATH="$HOME/bin:$PATH"
fi

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/.local/bin" ] ; then
PATH="$HOME/.local/bin:$PATH"
fi

The default content of the ~/.profile is simple. In most cases, it inherits whatever is in the ~/.bashrc, and adds some user specific executable filepath to the environment variable PATH. So if there are commands that make the shell look colorful in the ~/.bashrc, the login shell should also look colorful.

~/.bash_profile

Unfortunately, in most of my login trials, the shells were never colorful, and sometimes the environment variables did not match my expectation. In those cases, this is because there exists a ~/.bash_profile and therefore ~/.profile or ~/.bashrc is never executed. Usually the ~/.bash_profile will be empty, which means that we would not have the environment and appearance that we have in our local shell.

To make the login shell “back to normal”, we could either delete the ~/.bash_profile or modify the ~/.bash_profile by adding some commands like

1
. "$HOME/.profile"

Caveats

Sometimes, a non-color shell could be helpful. It can be used to indicate that you are not working in local shell, and that what you are seeing could either be a Docker shell or a remote login shell. When we know what shell we are dealing with, we will be more likely to avoid dangerous operations. For example, in a Docker shell, we could do almost anything, such as rm -rf / without sudo, without harming the local system.

Acknowledgement

I would like to thank Liam Keane from Hacker News for correcting the grammars and polishing the words in the blog post.

Author

Lei Mao

Posted on

09-09-2020

Updated on

10-26-2020

Licensed under


Comments