Why ~/.bash_profile is not getting sourced when opening a terminal?
Solution 1
~/.bash_profile
is only sourced by bash when started in login mode. That is typically when you log in at the console (Ctrl+Alt+F1..F6), connect via ssh, or use sudo -i
or su -
to run commands as another user.
When you log in graphically, ~/.profile
will be specifically sourced by the script that launches gnome-session (or whichever desktop environment you're using). So ~/.bash_profile
is not sourced at all when you log in graphically.
When you open a terminal, the terminal starts bash in (non-login) interactive mode, which means it will source ~/.bashrc
.
The right place for you to put these environment variables is in ~/.profile
, and the effect should be apparent next time you log in.
Sourcing ~/.bash_profile
from ~/.bashrc
is the wrong solution. It's supposed to be the other way around; ~/.bash_profile
should source ~/.bashrc
.
See DotFiles for a more thorough explanation, including some history of why it is like it is.
(On a side note, when installing openjdk via apt, symlinks should be set up by the package, so that you don't really need to set JAVA_HOME
or change PATH
)
Solution 2
You can check if your Bash shell is started as a login-shell by running:
shopt login_shell
If the reply is off
you are not running a login shell.
Read the Bash manual's invocation section on how Bash reads (or does not read) different configuration files.
Excerpt from man bash
:
When bash is invoked as an interactive login shell, or as a non-interactive 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.
su
on the other hand also does not start a login shell by default, you have to tell it to do so by using the --login
option.
Solution 3
I think it is worth mentioning that you can change the default of gnome-terminal to use a login shell (ie. bash -l) by editing the profile preferences.
go to Edit -> Profile Preferences -> Title and Command tab check the "Run command as a login shell" option
Solution 4
If you open a terminal or run su
the shell is not executed as a login shell but as a normal interactive shell. So it reads ~/.bashrc
but not ~/.bash_profile
. You can run su
with the -l
option to make it run your shell as a login shell.
When you are working with a GUI the shell is usually never run as a login shell so it's usually fine to put all yout stuff in ~/.bashrc
.
Solution 5
TL;DR
In classical recommended ubuntu setup, ~/.bash_profile
gets evaluated only in specific occasions. And it makes sense.
Put your stuff in ~/.bashrc
, it'll get evaluated everytime.
Ok, I want to understand, why does this make sense ?
Keypoints to understand what is going on:
- all processes on linux have and uses environment variables
- environment variables are inherited
- thus setting them once on the father of all your process is enough (especially if it requires some computation time.)
- the father of all your process is typically launched after you log in on your device (give your credentials).
- there are things you might want to do only once when you log in on your computer (check for new mail for instance...).
So "login" time is typically:
- In console mode, when you login (with Ctrl-Alt F1) or through
ssh
, as the shell will be the father of all process, it'll load your~/.bash_profile
. - In graphic mode, when you open your session, the first process
(
gnome-session
for classical ubuntu) will be in charge to read
.profile
.
Ok, so where to put my stuff ?
It's rather complex, the full story is here. But here is a run down that is pretty common for ubuntu users. So considering that:
- you use
bash
shell, - you have a
~/.bash_profile
and follow the recommendation to add the loading of~/.bashrc
in your~/.bash_profile
so as to get at least one file that gets evaluated whatever is the invocation mecanism.
This is a quick suggestion of where to put things.
-
~/.bashrc (Gets evaluated in all occasion, provided you follow the recommendation)
For fast-evaluation environment variable and code for your user-only and bash-only command-line usage (aliases for instance). bashism are welcome.
It gets loaded on itself upon:
- make a new shell window/pane in graphical sessions.
- calling
bash
-
screen
new pane or tab. (nottmux
!) - any bash instance in a graphical console client
(
terminator
/gnome-terminal
...) if you don't tick option "run command as login shell".
And it will get loaded in all the other occasion thanks to the prior recommendation.
-
~/.bash_profile (Gets evaluated in specific occasion only)
For slow-evaluation environment variable and code for your user-only and console-session processes. bashism are welcome. It gets loaded on:
- console login (Ctrl-Alt F1),
- ssh logins to this machine,
-
tmux
new pane or windows (default settings), (notscreen
!) - explicit calls of
bash -l
, - any bash instance in a graphical console client
(
terminator
/gnome-terminal
...) only if you tick option "run command as login shell".
-
~/.profile (Gets evaluated only in graphical-session)
For slow-evaluation environment variables and with no-bashism for your user-only and all graphical-session processes. It gets loaded upon login in your graphical UI.
Related videos on Youtube
Viriato
My professional interests are as follows: Enterprise Java Development (Spring&Hibernate). Groovy and Grails Web Development. Up & coming languages for the JVM such as Clojure and Scala. OLTP and OLAP Database Modeling. Enterprise Application Integration (Talend, Pentaho BI, TIBCO BusinessWorks, DataStage). Web 2.0 technologies: DOM frameworks, Ajax frameworks, 360gs CSS framework, WordPress, Security. Mobile development (iPhone & Android).
Updated on September 18, 2022Comments
-
Viriato over 1 year
Problem
I have an Ubuntu 11.04 Virtual Machine and I wanted to set up my Java development environment. I did as follows
sudo apt-get install openjdk-6-jdk
Added the following entries to ~/.bash_profile
export JAVA_HOME=/usr/lib/jvm/java-6-openjdk export PATH=$PATH:$JAVA_HOME/bin
Save the changes and exit
Open up a terminal again and typed the following
echo $JAVA_HOME (blank) echo $PATH (displayed, but not the JAVA_HOME value)
Nothing happened, like if the export of JAVA_HOME and it's addition to the PATH were never done.
Solution
I had to go to ~/.bashrc and add the following entry towards the end of file
#Source bash_profile to set JAVA_HOME and add it to the PATH because for some reason is not being picked up . ~/.bash_profile
Questions
- Why did I have to do that? I thought bash_profile, bash_login or profile in absence of those two get executed first before bashrc.
- Was in this case my terminal a non-login shell?
- If so, why when doing su after the terminal and putting the password it did not execute profile where I had also set the exports mentioned above?
-
Viriato about 12 yearssymlinks whre setup by the package by JAVA_HOME and it's addition to the PATH where not that is why I was doing what I was doing. I deleted the bash_profile and added my exports in .profile. Restarted my Virtual Machine and indeed I was able to do echo $JAVA-HOME
-
Viriato about 12 yearsThat is what I had done and it worked, but check what the guy in the bottom says, he suggests is a bad idea to put it in bashrc and put it on the profile instead. ....Hey both ways work, thanks a lot.
-
Viriato about 12 yearsThanks a lot for the shotp login_shell command. Awesome!!
-
jcollum about 11 yearsI've found that when opening a Terminal from the sidebar in Ubuntu 12 the ~/.profile file is not loaded.
-
geirha about 11 years@jcollum That's good.
.profile
should only be sourced when you log in. -
jcollum about 11 yearsoh, opening a terminal is not the same as logging in... I was thinking logging in to the terminal.
-
Bilal Mujeeb almost 11 yearsI've found that personal additions to be sourced each time when opening a Terminal do get loaded when placed on
.bash_aliases
. Would that be a better solution? -
geirha almost 11 years@JuanA.Navarro that's because your
~/.bashrc
sources~/.bash_aliases
. The few times you need to change an environment variable; update~/.profile
or~/.pam_environment
, then log out and back in. -
Bilal Mujeeb almost 11 yearsI know, that's why I added my additional code there. What I wanted to do was to configure options for the terminal (e.g. the prompt), but these were not loaded if I set them on
.profile
, even after a full restart. -
geirha almost 11 years@JuanA.Navarro Ah, you mean
PS1
andPROMPT_COMMAND
etc? Those are not environment variables, and they do indeed belong in~/.bashrc
as they only make sense for interactive shells. -
Lambart over 10 yearsIf you are using (the Ubuntu standard) Gnome Terminal, you can do Edit->Profile Preferences, go to the Title and Command tab, and check "Run command as a login shell". It will then source your .bash_profile or .profile whenever you open a terminal, as you probably expected it to.
-
terdon about 10 yearsBear in mind that
.profile
is ignored by bash if.bash_profile
exists. See my answer here andman bash
for more details. -
geirha about 10 years@terdon, yes, but bash is not involved when logging in graphically, so it goes straight for
.profile
. -
n611x007 about 8 years@geirha how the-structure-that-changes-state-when-you-login-from-console is called (foo-session?) and where it is to be found, opposed to merely starting an interactive shell? (in case it's called 'login' where is it to be found?) I did
man -k login
thenman 1 login
and see/var/run/utmp/
andlogin session
, however not the corresponding kernel-or-whatever structure. -
NyoNor over 6 yearsWhat are the downsides to enabling this setting?
-
muru about 6 yearsOn the occasions that bash does load a profile file, it will load
.profile
if.bash_profile
does not exist. -
vaab about 6 years@chris you are just loading code a little more code than necessary in a lot of occasion. It probably doesn't matter if your
~/.bash_profile
is evaluating really quickly, which is probably the case. A good thing to check is to chase out any calls to other processes that are usually quite costly. -
sofs1 over 4 yearsThank you very much for clear explanation. it helps newbies like me. In Mac Mojave , if I put variables in ~/.bashrc and do source, and then if I do
env
I don't see env variables set (I tried closing iTerm and re-opening). But I notice that when I installed Android studio and other apps, all those env vars were set in/.bash_profile
. So When I added in/.bash_profile
it worked like charm. Why is that? -
Nikhil Shrivastava over 3 yearsI checked the 'Run command as a login shell' but now every time I open a terminal, I get
-bash: /home/nikhil/.bash_profile: line 1: unexpected EOF while looking for matching
"`-bash: /home/nikhil/.bash_profile: line 2: syntax error: unexpected end of file
-
YorSubs over 3 yearsSomething that troubles me about this: say that someone puts cosmetic junk/fun things into
~/.bashrc
(like screenfetch / figlet stuff etc) so that they get some output on opening a console. Then, if they run a one line shell script that does some simple thing, that is going to always hit.bashrc
. Therefore, it seems crazy to put everything into.bashrc
. Also, what then is the point of.bash_profile
if you put everything into.bashrc
? I don't get it. Linux / bash usually make sense but this is all seems a convoluted and self-contradictory mess made up by a drunk person. -
YorSubs over 3 yearsTo be specific: • If I want code to run in both graphical and interactive login shells, where should I put that code? • If I want code to run just in graphical terminals, where should I put that code? • If I want code to only run in interactive login shells, where should I put that code? The answer seems to be "umm, bash is just a broken confusing mess, just put the code anywhere then try to insert weird connecting chains to try and make things dotsource other things". It's all really weird ... right?
-
Antonin Décimo over 3 yearsThis flowchart states that
.bash_profile
,.bash_login
or.profile
are sourced with a login shell, whether the shell is interactive or not doesn't matter. Is the flowchart wrong, or should the answer be modified? -
geirha over 3 years@AntoninDécimo thanks! Took nearly 9 years for someone to notice my error. I've edited the answer.
-
Kellen Stuart over 2 years@YorSubs You're not wrong. The fundamental thing to understand is
.bashrc
is what is executed when BASH is loaded. What you do from there if up to you. I would agree with you that dotsourcing other things is unnecessary, but I believe that practice was started by developers trying to separate the generated code in the.bashrc
from their custom code.bash_profile
.