Why ~/.bash_profile is not getting sourced when opening a terminal?

389,292

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. (not tmux !)
    • 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), (not screen !)
    • 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.

Share:
389,292

Related videos on Youtube

Viriato
Author by

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, 2022

Comments

  • Viriato
    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

    1. sudo apt-get install openjdk-6-jdk
    2. Added the following entries to ~/.bash_profile

      export JAVA_HOME=/usr/lib/jvm/java-6-openjdk
      
      export PATH=$PATH:$JAVA_HOME/bin
      
    3. Save the changes and exit

    4. Open up a terminal again and typed the following

      echo $JAVA_HOME   (blank)
      echo $PATH        (displayed, but not the JAVA_HOME value)
      
    5. 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

    1. 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.
    2. Was in this case my terminal a non-login shell?
    3. 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
    Viriato about 12 years
    symlinks 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
    Viriato about 12 years
    That 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
    Viriato about 12 years
    Thanks a lot for the shotp login_shell command. Awesome!!
  • jcollum
    jcollum about 11 years
    I've found that when opening a Terminal from the sidebar in Ubuntu 12 the ~/.profile file is not loaded.
  • geirha
    geirha about 11 years
    @jcollum That's good. .profile should only be sourced when you log in.
  • jcollum
    jcollum about 11 years
    oh, opening a terminal is not the same as logging in... I was thinking logging in to the terminal.
  • Bilal Mujeeb
    Bilal Mujeeb almost 11 years
    I'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
    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
    Bilal Mujeeb almost 11 years
    I 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
    geirha almost 11 years
    @JuanA.Navarro Ah, you mean PS1 and PROMPT_COMMAND etc? Those are not environment variables, and they do indeed belong in ~/.bashrc as they only make sense for interactive shells.
  • Lambart
    Lambart over 10 years
    If 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
    terdon about 10 years
    Bear in mind that .profile is ignored by bash if .bash_profile exists. See my answer here and man bash for more details.
  • geirha
    geirha about 10 years
    @terdon, yes, but bash is not involved when logging in graphically, so it goes straight for .profile.
  • n611x007
    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 then man 1 login and see /var/run/utmp/ and login session, however not the corresponding kernel-or-whatever structure.
  • NyoNor
    NyoNor over 6 years
    What are the downsides to enabling this setting?
  • muru
    muru about 6 years
    On the occasions that bash does load a profile file, it will load .profile if .bash_profile does not exist.
  • vaab
    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
    sofs1 over 4 years
    Thank 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
    Nikhil Shrivastava over 3 years
    I 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
    YorSubs over 3 years
    Something 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
    YorSubs over 3 years
    To 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
    Antonin Décimo over 3 years
    This 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
    geirha over 3 years
    @AntoninDécimo thanks! Took nearly 9 years for someone to notice my error. I've edited the answer.
  • Kellen Stuart
    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.