Ubuntu – Where is the PATH variable being set

bashbashrcenvironment-variablesjavaprofile

I'm trying to set my path variable to look like this:

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/jgrande/android-sdk-linux/platform-tools:/usr/lib/jvm/java-7-openjdk-amd64/bin/:/usr/lib/jvm/java-7-openjdk-amd64/jre/bin

And for some reasons, no matter what file I edit, the variable always ends up looking like this (with the java path repeating a bunch of times):

PATH=/usr/local/java/jdk1.7.0_79/bin:/home/jgrande/bin:/usr/local/java/jdk1.7.0_79/bin:/home/jgrande/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/local/java/jdk1.7.0_79/bin:/usr/local/java/jdk1.7.0_79/jre/bin:/usr/local/java/jdk1.7.0_79/bin:/usr/local/java/jdk1.7.0_79/jre/bin

I've tried to edit my personal .bashrc and .profile as well as /etc/environment, /etc/bash.bashrc, /etc/profile, and set it in /etc/profile.d. Now, there is jdk.sh in /etc/profile.d where the PATH variable is identical to the incorrect one I posted above. However, I tried to comment out the line and even remove jdk.sh altogether and that still didn't fix it.

Otherwise, I've noticed that if I log in as another user, I'll have the correct PATH variable, and don't have the messed up one with java being repeated a bunch of times.

So, I was wondering, where else could my PATH variable be defined that I haven't checked yet?

Best Answer

The PATH could be set in any of the various files bash reads when it starts. To find them all, run this:

grep --color -H 'PATH=' ~/.bashrc ~/.profile ~/.bash_profile ~/bash.login \
                     ~/.bash_aliases /etc/bash.bashrc /etc/profile \
                     /etc/profile.d/* /etc/environment 2> /dev/null

Those are the standard ones. If you are also sourcing other files from one of those, things can get more complex.

Anyway, to fix it—assuming you haven't done anything to the global files in /etc/—you can run this:

sed -i '/PATH=/d' ~/.bashrc ~/.profile ~/.bash_profile ~/bash.login ~/.bash_aliases 

That will delete any lines setting PATH from those files. Now, add the right one in the right place:

pp='PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/jgrande/android-sdk-linux/platform-tools:/usr/lib/jvm/java-7-openjdk-amd64/bin/:/usr/lib/jvm/java-7-openjdk-amd64/jre/bin'
[[ -e '~/.bash_profile' ]] && echo "$pp" >> ~/bash_profile ||
                              echo "$pp" >> ~/.profile

When invoked as a login shell, bash reads .bash_profile if present and, if not, it reads ~/.profile (it will ignore .profile if .bash_login is present but I assume it isn't). So, the commands above will first save your desired path as $pp and then check whether a ~/.bash_profile exists, add the path definition to it if it does and, if it doesn't, it will add it to ~/.profile.

In the future, to avoid this kind of issue, use a function to add directories to your $PATH. Add these lines to your ~/.profile:

pathmunge () 
{ 
    if ! echo $PATH | /bin/egrep -q "(^|:)$1($|:)"; then
        if [ "$2" = "after" ]; then
            PATH=$PATH:$1;
        else
            PATH=$1:$PATH;
        fi;
    fi
}

Then, to add something to the beginning of your $PATH, add this line to ~/.profile:

pathmunge "/path/to/foo"

And to add it to the end:

pathmunge "/path/to/foo" after

The function will only add a new directory to the $PATH if it isn't already there.