I'm using Linux Mint. My login shell (cat /etc/passwd | grep myUserName) is bash.

After I start my graphical desktop environment and run a terminal emulator from it, I can see that .bash_profile is not sourced (environment vars that are exported in it are unset). But if I log in from a text console (ctrl+alt+F1) or manually run bash -l from the terminal emulator, .bash_profile works fine.

Am I wrong when I think that .bash_profile should be sourced when X starts and all export'ed vars should be available in the terminal, running from X?

P.S. Placing everything in .bashrc and sourcing it from .bash_profile is not good idea (https://stackoverflow.com/questions/902946/): environment stuff should be sourced only once.

up vote 32 down vote accepted

The file ~/.bash_profile is read by bash when it is a login shell. That's what you get when you log in in text mode.

When you log in under X, the startup scripts are executed by /bin/sh. On Ubuntu and Mint, /bin/sh is dash, not bash. Dash and bash both have the same core features, but dash sticks to these core features in order to be fast and small whereas bash adds a lot of features at the cost of requiring more resources. It is common to use dash for scripts that don't need the extra features and bash for interactive use (though zsh has a lot of nicer features).

Most combinations of display manager (the program where you type your user name and password) and desktop environment read ~/.profile from the login scripts in /etc/X11/Xsession, /usr/bin/lightdm-session, /etc/gdm/Xsession or whichever is applicable. So put your environment variable definitions in ~/.profile. Make sure to use only syntax that dash supports.

So what should you put where?

  • A good .bash_profile loads .profile, and loads .bashrc if the shell is interactive.

    . ~/.profile
    if [[ $- == *i* ]]; then . ~/.bashrc; fi
    
  • In .profile, put environment variable definitions, and other session settings such as ulimit.

  • In .bashrc, put bash interactive settings such as aliases, functions, completion, key bindings (that aren't in .inputrc), …

See also Difference between Login Shell and Non-Login Shell? and Alternative to .bashrc.

  • many things learnt from single answer :) – mtk Jul 24 '16 at 20:31

.bash_profile is the startup configuration script of bash. There exists no standard mandating X to source .bash_profile.

What you are thinking of is rather .profile. Originally it was the startup configuration file of the bourne shell (sh). Today many distributions have their desktop environment set up to source .profile. Note that this is also not a standard, but it seems to be a convention.

Debian used to source .profile at graphical login (wiki page as of 2013) now it doesn't (wiki page as of 2016).

Arch sources .xprofile at graphical login (wiki page as of 2013).

Ubuntu used to discourage using .profile (wiki page as of 2013) now it doesn't discourage anymore (wiki page as of 2016).


Regarding your other question: Why doesn't my ~/.bash_profile work? That is the expected behaviour.

The behaviour, in short, is as follows:

  • bash started as an interactive login shell: reads ~/.profile
  • bash started as an interactive non-login shell: reads ~/.bashrc

For more details see my answer to a similar question in askubuntu: https://askubuntu.com/questions/132276/configure-gnome-terminal-to-start-bash-as-a-login-shell-doesnt-read-bashrc/132319#132319

  • 1
    Some of this is correct, but “always read ~/.bashrc” is bad advice: you should only read .bashrc from an interactive shell. You've missed the core problem here which is that when logging in under X, there is no login instance of bash (under most display manager/desktop environment combinations, including evidently AntonioK's). – Gilles Aug 25 '13 at 22:45
  • Thank you for your feedback. I hope I updated my answer well enough to resolve your complaints. Regarding my advice to "always read .bashrc", I meant always for an interactive shell. I have clarified that part. I hope it is not misleading anymore. – lesmana Aug 26 '13 at 2:21
  • 2
    "Ubuntu specifically discourages using .profile (link)" The wiki did once (absurdly) discourage that; that's been fixed. (Note /etc/profile does remain discouraged for systemwide assignments, in preference for adding scripts to /etc/profile.d.) Per-user .profile files are now presented as one of the recommended ways to set per-user environment variables: "Suitable files for environment variable settings that should affect just a particular user (rather than the system as a whole) are ~/.pam_environment and ~/.profile." – Eliah Kagan Oct 4 '14 at 2:37
  • The linked page about Debian specifies that Debian does not read ~/.profile for graphical login and ~/.xsessionrc should be used instead. – karora Mar 20 at 11:29
  • thanks for noticing. the wiki page got updated. i linked to the versions as they were at time of answer. – lesmana Mar 21 at 8:38

In your question, you refer to https://stackoverflow.com/questions/902946/ as recommending not to source, when the accepted answer prescribes to

  • Put my PATH setup into a .profile file (because I sometimes use other shells)
  • Put my Bash aliases and functions into my .bashrc file
  • Then use this [EDITED: snip code-comments]:

    .bash_profile:

    #!/bin/bash
    # echo "Loading ${HOME}/.bash_profile"
    source ~/.profile # Get the paths
    source ~/.bashrc  # get aliases
    

Putting it all in .profile did not work for me on Linux Mint. Using .bashrc worked fine.

A couple of issues arise when trying to reload/source ~/.profile file. [This refers to Ubuntu linux - in some cases the details of the commands will be different]

  1. Are you running this directly in terminal or in a script?
  2. How do you run this in a script?

Ad. 1)

Running this directly in terminal means that there will be no subshell created. So you can use either two commands:

source ~/.bash_profile

or

. ~/.bash_profile

In both cases this will update the environment with the contents of .profile file.

Ad 2) You can start any bash script either by calling

sh myscript.sh 

or

. myscript.sh

In the first case this will create a subshell that will not affect the environment variables of your system and they will be visible only to the subshell process. After finishing the subshell command none of the exports etc. will be applied. THIS IS A COMMON MISTAKE AND CAUSES A LOT OF DEVELOPERS TO LOOSE A LOT OF TIME.

In order for your changes applied in your script to have effect for the global environment the script has to be run with

.myscript.sh

command.

In order to make sure that you script is not runned in a subshel you can use this function. (Again example is for Ubuntu shell)

#/bin/bash

preventSubshell(){
  if [[ $_ != $0 ]]
  then
    echo "Script is being sourced"
  else
    echo "Script is a subshell - please run the script by invoking . script.sh command";
    exit 1;
  fi
}

I hope this clears some of the common misunderstandings! :D Good Luck!

The simple solution is to make the terminal a login terminal. For Gnome terminal under 'Tile and Command' of the default profile you can check the box "Run command as a login shell". This article explains the difference between a login shell and one that is not.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.