2

I am trying to get Oracle Java 7 update 3 working correctly on Debian 6. I have downloaded and set up the files in /usr/java/jre1.7.0_03. I have also set the following two lines at the end of /etc/bash.bashrc:

export JAVA_HOME=/usr/java/jre1.7.0_03
export PATH=$PATH:$JAVA_HOME/bin

Logging in as other users and root is fine, Java can be found:

chris@mc:~$ java -version
java version "1.7.0_03"
Java(TM) SE Runtime Environment (build 1.7.0_03-b04)
Java HotSpot(TM) 64-Bit Server VM (build 22.1-b02, mixed mode)

However there are two cases where Java cannot be found as detailed below. Note that both of these worked fine when I have previously installed OpenJDK Java 6 via aptitude, but I need Oracle Java 7 for various reasons.

  1. Most importantly, I cannot run commands as another user via su, despite the PATH showing that Java should be present. The user was created with adduser chris

    root@mc:~# su chris -c "echo $PATH"
    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/java/jre1.7.0_03/bin:/bin
    root@mc:~# su chris -c "java -version"
    bash: java: command not found
    root@mc:~# su chris -c "/usr/java/jre1.7.0_03/bin/java -version"
    java version "1.7.0_03"
    ...
    

    How can it be in the PATH but not be found? Update 05/04/2012: explained by Daniel, to do with it being a non-interactive shell so files such as /etc/profile and /etc/bash.bashrc are not executed. Doing a full swap to that user and running Java works:

    root@mc:~# su chris
    chris@mc:/root$ java -version
    java version "1.7.0_03"
    ...
    
  2. I run a script on start up which exhibits similar but slightly different problems. The script is located in /etc/init.d/start-mystuff.sh and calls a jar:

    #!/bin/bash
    # /etc/init.d/start-mystuff.sh
    java -jar /opt/Mars.jar
    

    I can confirm that the script runs on start up and the exit code is 127, which indicates command not found. Inserting a line to print/save the PATH shows that it is:

     /sbin:/usr/sbin:/bin:/usr/bin
    

    This second problem isn't as important because I can just point directly to the Java executable in the script, but I am still curious!

I have tried setting the full PATH and JAVA_HOME explicitly in /etc/environment which didn't help. I have also tried setting them in /etc/profile which doesn't seem to help either. I have tried logging in and out again after setting PATH in the various locations (duh!).

Anyway, long post for what will probably have a simple one line solution :( Any help with this would be greatly appreciated, I have spent far too long trying to fix it by myself.

Motivation

The first problem may seem obscure but in my system I have users that are not allowed SSH access yet I still want to run processes as them. I have a ton of scripts operating in this way and don't want to have to change them all.

3 Answers 3

3

See: update-alternatives

Also: Debian generally discourages developers relying on ENV variables, you have discovered one reason why.

Its not that they are taboo its just that they should not be expected to always be available.

Note: Adding your java path at the end of the existing path means that any other java will be found, and used, first.

(i.e. the (symlink) under /usr/bin )

so:

ls -lah /usr/bin/java

says:

lrwxrwxrwx 1 root root 22 Apr 22 2011 /usr/bin/java -> /etc/alternatives/java

file $(which java)

/usr/bin/java: symbolic link to `/etc/alternatives/java'

file /etc/alternatives/java

/etc/alternatives/java: symbolic link to `/usr/lib/jvm/java-6-openjdk-i386/jre/bin/java'

**<side issue> and also serves to demonstrate why $(exec in subshell style) is preferable, to "backtick exec mode" , or " eval this ".

(( as `` '' and "" gets way too confusing, for me at least, and doesn't always work as expected in all shells all of the time. Investigate POSIX mode AKA /bin/sh ))

</side issue>**

man update-alternatives explains why this alternative system exists ...

meantime

update-alternatives --config java 

may help.

/usr/local/ is a good place to install source built packages...

There are also other ways to skin your cat.

Including:

  • hand re-pointing the /usr/bin/java link :)

(though watch out for upgrades or dependency installs resetting it.. not a great choice but it works)

  • setting an alias for java per user [1]

  • prepending $PATH in the users .bashrc

(you can source .bashrc from .bash_profile if you like)

  • calling the specific versions full path per instance

(safest bet but probably not practical)

[1] .alias or .bashrc

help alias

(its a bash builtin)

Finally an example for good or ill: taken from my Debian .bash_profile...

# include .bashrc if it exists

if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi

# set PATH so it includes user's private bin if it exists
if [ -d ~/bin ] ; then
    PATH=~/bin:"${PATH}"
fi

Hope this helps rather than hinders

Pete

3
  • Hi Pete, I'll have a play around with update-alternatives; it does seem much better than messing with environment variables. Maybe I should have mentioned in my original post but I started from a minimal install of Debian with no version of Java on it. And I think everyone should be discouraged from relying on env variables, no matter what their system is ;) thanks! Apr 5, 2012 at 16:54
  • @milkmansrevenge Cool. Good luck, It looks more complex than it is.
    – petergozz
    Apr 5, 2012 at 17:50
  • Yup, it turned out to be ridiculously simple. One line as predicted :) update-alternatives --install /usr/bin/java jre7u3 /usr/java/jre1.7.0_03/bin/java 5. I also found another way to solve it using $BASH_ENV but update-alternatives is the best. I'll update my question so all of this is clear to any other visitors soon. Edit: Can't seem to tag you with @, guess my rating is too low. Apr 5, 2012 at 19:59
1

Many questions in one go, but:

1. You do

# su chris -c "echo $PATH"

This will substitute the variable $PATH before the command is run, which will give the $PATH for root. Try

# su chris -c "echo $HOME"

to see what I mean.

Instead, you can do

# su chris -c 'echo $PATH'

which will hinder the shell from expanding the variable in the first case, and instead actually get chris's $PATH. You will most likely find that the changes have not permeated to that user.

Why not then? /bin/sh is linked to /bin/dash on Debian systems, and not /bin/bash. Dash won't read /etc/bash.bashrc. Perhaps you got Dash as default shell for the user chris when he was created. Look in /etc/passwd to see if this is the case.

Perhaps this clarifies question 2 as well.


UPDATE: Ah, /etc/bash.bashrc is only read for interactive shells. Read man bash, section "FILES". You don't start an interactive shell when you use su in that way.


Update 2: This example is one way:

# su chris -c 'myvar="hi there"; echo $myvar'
hi there

or similarly:

# su chris -c 'export myvar="hi there"; echo $myvar; export | grep myvar'
hi there
declare -x myvar="hi there"

(with export, the variable is available to spawned sub-processes as well, as usual).

4
  • Thanks, I didn't realise it was such a simple substitution when using " rather than ', however: chris:x:1001:1001:,,,:/home/chris:/bin/bash indicates that /bin/bash is the default shell for chris right? Apr 5, 2012 at 14:54
  • Yes, it does indeed indicate that. However, read the updated section of my answer regarding interactive shells and start up files. Apr 5, 2012 at 15:05
  • @milkmansrevenge: forgot to highlight your username so you'll get notified, and seem to have missed the edit time with an infinitesimal amount of time... Read my above comment. Apr 5, 2012 at 15:12
  • thanks. I guess my question then simply becomes: How do I set the $PATH for non-interactive shells? The "FILES" section for man bash does hint that my solutions won't work. I'll have a search around for solutions and update my post if I find anything. Apr 5, 2012 at 15:32
0

You can use

sudo -u <user> -i 

which will read .bashrc / .bash_profile.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .