Understanding .bashrc and .bash_profile
On a server when I login as root I see .bashrc
(Ubuntu 10.10).
On my Mac I have a .bash_profile
Does Ubuntu always have only a .bashrc
file and not .bash_profile
? (I'm just confused, so asking, I realize they are different o/s's but maybe there is a relationship somehow?)
On my server, I want to create an alias, should I put it in .bashrc
?
What if I want this alias to be applied so all users can use it?
Solution 1:
Bash aliases should go in the .bash_aliases
or .bashrc
files in individual home directories. If you must create global bash aliases, they can go in /etc/bash.bashrc
, but it is often best simply to add them to the .bash_aliases
or .bashrc
files in /etc/skel
so they are inherited by newly created users.
It is virtually always wrong to define an alias in in .profile
, .bash_profile
, or /etc/profile
.
To understand why, one must understand under what circumstances commands from each of these files are run. There are misconceptions about this, which I address below.
Even though you want to define aliases for multiple users, you should be familiar with how they are defined for individual users, so that you can decide on the best method of doing what you need.
Aliases for Individual Users
Especially if you use a GUI, most of your interactive shells are probably non-login shells. Even if you never use a GUI, you probably still use non-login shells with some frequency. You'll want your aliases to work in these shells.
Especially if you ever log in non-graphically in a virtual console or via SSH, you probably use login shells some of the time. So you'll want your aliases to work in interactive login shells also.
When an interactive, non-login shell starts, it sources .bashrc
in the user's home directory. By default in Ubuntu, each user's .bashrc
itself sources .bash_aliases
, if it exists.
- To source a file is to cause its contents to be run in the current shell. Changes to the shell environment made in a file that is sourced persist even after all the commands in the file have been run.
Reading the comments in Ubuntu's default .bashrc
reveals that it is officially intended that aliases go in .bashrc
or .bash_aliases
. .bashrc
already contains some alias definitions (run grep '^[[:blank:]]*alias' ~/.bashrc
to see them), and gives explicit advice about where to put new such definitions:
# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.
if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fi
But what about interactive login shells? Instead of .bashrc
, login shells source .profile
.
- ...Unless
.bash_login
exists, then it gets sourced instead. - ...Unless
.bash_profile
exists, then it gets sourced instead.
However, the good news is that by default in Ubuntu, commands in .bashrc
will also run in interactive login shells because the default .profile
checks if the current shell is bash (and if .bashrc
exists), and if so, sources .bashrc
:
# if running bash
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
I suggest users define new bash aliases in .bash_aliases
in their home directories (creating it if it doesn't already exist). This is a particularly clean and simple way to make alias definitions permanent at the per-user level.
Aliases should not be defined in .profile
because they would remain undefined in non-login shells. Unlike much of a bash shell's environment, aliases are not exported to child shells:
ek@Io:~$ alias hi='echo "Greetings, $USER!"'
ek@Io:~$ hi
Greetings, ek!
ek@Io:~$ bash
ek@Io:~$ hi
hi: command not found
In particular, by default most desktop environments cause .profile
to be sourced on graphical login, but:
- This is not necessarily done by a bash shell, so alias definitions may not even be processed, and more importantly
- even if alias definitions are processed, they are not passed on to child processes. Particularly, they are not passed on to shells created by opening a Terminal window!
Aliases should not be defined in .bash_profile
(or .bash_login
) for the very same reason, but also for another reason. Naively creating one of these files and putting just alias definitions in it prevents any of the code in .profile
from running!
In situations where .bash_profile
or .bash_login
really is useful, typically one sources .profile
somewhere in them, which solves that problem. (Then the only remaining problem is that, like with .profile
, defining aliases in .bash_profile
or .bash_login
doesn't work right.)
Aliases for New Individual Users, Automatically
When a user account of the type intended to represent a real human being is created, a new directory is typically made to serve as their home directory. The contents of /etc/skel
are then copied to their home directory. This is how multiple users start out with some similar configuration files in their home directories. In Ubuntu, this includes .profile
, .bashrc
, and some other files.
To change what aliases are defined for new users, you can simply put them in /etc/skel/.bash_aliases
(you will have to create it) or /etc/skel/.bashrc
.
If you edit an already-existing file in /etc/skel
you may want to back it up first--but you shouldn't put the backup in /etc/skel
, or it, too, will be copied into new users' home directories.
This is likely the best way for you to add new aliases for multiple users. Existing users can simply add the aliases themselves. If you define the aliases in /etc/skel/.bash_aliases
, you can simply direct them to that file, which they may choose to copy into their home directories (or add into their own custom .bash_aliases
file).
It's trivial for a user to undefine an alias. Additionally, aliases are not extremely robust; they work only in particular circumstances. If you need to create a new command that works all the time, for everyone, you should not implement that command as an alias. And you cannot successfully force aliases on users who don't want them--they can simply unalias
them.
Global Aliases, for All Users
Though I advise you to avoid this approach, you can define aliases in the the global /etc/bash.bashrc
file. They will then be defined both for interactive non-login shells and for interactive login shells. The reason is, before any of the files in the user's home directory are sourced:
- Login shells (and only login shells and other processes behaving like login shells) run commands from
/etc/profile
automatically. - Only non-login shells run commands in
/etc/bash.bashrc
automatically, but - Ubuntu's default
/etc/profile
checks if the running shell is bash (and if/etc/bash.bashrc
exists) and, if so, sources/etc/bash.bashrc
.
This is analogous to how the default per-user .profile
sources the per-user .bashrc
if the shell is bash (as detailed above).
Here's what the actual code for this looks like in the default /etc/profile
:
if [ "$PS1" ]; then
if [ "$BASH" ] && [ "$BASH" != "/bin/sh" ]; then
# The file bash.bashrc already sets the default PS1.
# PS1='\h:\w\$ '
if [ -f /etc/bash.bashrc ]; then
. /etc/bash.bashrc
fi
else
if [ "`id -u`" -eq 0 ]; then
PS1='# '
else
PS1='$ '
fi
fi
fi
That block also performs other tasks. Specifically, the outer if
checks if the shell is likely to be interactive (by checking that the prompt text is non-empty), then checks if the current shell is bash and sources /etc/bash.bashrc
if it is, and if not does some work that, for bash, is already done in /etc/bash.bashrc
.
You should not define global aliases in /etc/profile
for the same reason users should not define them in their local .profile
s: if you do, they will be defined only for login shells, and not for their child shells.
Finally, note that, unlike the default per-user .bashrc
, the default /etc/bash.bashrc
file does not contain anything about aliases. It is somewhat unusual to give users aliases in a file where they cannot edit or disable them. (Of course, they still can do that, by overriding their definitions in their own local .bashrc
, .bash_aliases
, or elsewhere.)
Further Reading
- Why is /etc/profile not invoked for non-login shells?
- How to create a permanent “alias”?
- How do I create a permanent Bash alias?
- Why must I do
. .bash_profile
every time I create a new alias?
Solution 2:
Here's some nice reading on it. ".bash_profile is executed for login shells, while .bashrc is executed for interactive non-login shells"
So for your alias, use .bash_profile