9

I have a shell script to set up some environment variables and launch whatever program I send in as an argument:

export PATH=$HOME/local/bin:$PATH
export LD_LIBRARY_PATH=$HOME/local/lib:$LD_LIBRARY_PATH
export TESTER="MY TEST VAR"

$@

When I use this to call bash for example it works:

kjfletch@flatbed:~$ envrun.sh bash
kjfletch@flatbed:~$ echo $LD_LIBRARY_PATH
/home/kjfletch/local/lib:
kjfletch@flatbed:~$ echo $TESTER
MY TEST VAR

When I use it to call a terminal (xterm, aterm, ...) my LD_LIBRARY_PATH gets unset:

kjfletch@flatbed:~$ echo $LD_LIBRARY_PATH

kjfletch@flatbed:~$ echo $TESTER

MY TEST VAR

Why does this happen? How can I stop this? (I am running Debian 5.0)

Update

My terminal is not calling bash as a login:

kjfletch@flatbed:~$ echo $0
bash

My LD_LIBRARY_PATH does not show up in any of the bash startup files (apart from .bash_history and ~/.profile does not exist.):

kjfletch@flatbed:~$ grep "LD" ~/.bash*
kjfletch@flatbed:~$ grep "LD" /etc/bash.bashrc 
kjfletch@flatbed:~$ grep "LD" /etc/profile 
2
  • Are any of those startup files calling the "source" command or the "." command to bring in other startup scripts? If so, one of those may be the culprit. Aug 25, 2009 at 12:34
  • Does not answer your question, but the really good thing would be to get rid of the need for LD_LIBRARY_PATH (reasons: 1 2 3). You could, for example, edit /etc/ld.so.conf, or compile whatever user-defined libs you have in ~/local in a way that they know where to find their libraries (see the links I gave).
    – DevSolar
    Jul 16, 2012 at 9:42

6 Answers 6

10

The terminal binary is most likely setgid to group utmp. Setuid and setgid binaries unset LD_LIBRARY_PATH for security reasons; see ld.so(8):

The necessary shared libraries needed by the program are searched for in the following order

  • Using the environment variable LD_LIBRARY_PATH (LD_AOUT_LIBRARY_PATH for a.out programs). Except if the executable is a setuid/setgid binary, in which case it is ignored.
4

In the terminal (xterm, aterm etc), check how the shell was invoked: A login shell will show "-bash" and a non-login shell will show "bash" when you call echo $0.

$ echo $0
-bash
$ bash
$ echo $0
bash

A login bash shell will read the following in order:

  1. /etc/profile
  2. ~/.bash_profile
  3. ~/.bash_login
  4. ~/.profile

Check if any of these files exist, and if they reset the variable. You'll also have to follow any files these files include.

If bash is not invoked as a login shell, it will still read the below files if is determined to be an interactive shell.

  1. /etc/bash.bashrc
  2. ~/.bashrc

A simple way to determine the kind of bash shell being invoked is to define your .bash_profile and .bashrc, and echo "Login shell" and "Interactive shell" respectively.

Once you know the kind of shell being invoked, you have the option of adding your script to the .bashrc or .bash_profile file in your home directory. Alternatively, you can disable the reset of LD_LIBRARY_PATH.

Note that if your .bashrc or .bash_profile is protected by a guard similar to the one below, you might have to call your script outside of it:

if [ "X$BASH_SOURCED" != "XYES" ]; then
        export BASH_SOURCED=YES

fi

Such guards are normally placed to prevent a script being sourced multiple times in a session.

Edit: If it is proving tedius to track down where the variable is being reset, and you have access to /etc/profile or /etc/bash.bashrc for example, you can temporarily add "set -x" near the top of the script to see all the commands that get executed. The output will be pretty verbose, so first do a "set -x" in your shell and run a few commands so you know what to expect.

3
  • +1 Thanks for the info. I have updated my OP in response to your answer.
    – kjfletch
    Aug 22, 2009 at 15:47
  • Do you see the same behaviour if you enter a new bash shell on the same terminal by typing bash? Btw, you'll also need to check files that are called from within /etc/bash.bashrc and /etc/profile - one of those might unset the variable. Alternatively, use the set -x debug option to get a dump of everything that gets done from the time the shell is created.
    – user4358
    Aug 22, 2009 at 16:00
  • The set -x dump makes no reference to LD_LIBRARY_PATH. Phantom unset.
    – kjfletch
    Aug 22, 2009 at 16:50
4

bash will use different start-up scripts depending on how it is started. There are seven different ways to start it, but the most important are login shells versus non-login interactive shells.

Check out the bash manual for more details. I would suspect the /etc/profile or the ~/.bash_profile is doing something to reset the LD_LIBRARY_PATH variable.


Edit: I think you have done all you reasonably can to show that bash does not have any startup script that unsets LD_LIBRARY_PATH. It is time to bring out the big guns.

The following command will display the entire environment as each process starts up, from bash to xterm, and anything else that happens to be involved -- you will probably get a large amount of output, so saving the output to a file is a good idea.

strace -v -f -e trace=process -o strace_output.txt envrun.sh xterm

Now, the file strace_output.txt will show each system call made by your script and every child process, and you will be able to see which process was the last to have LD_LIBRARY_PATH before it got removed.

2

(This question is very old, but I just encountered the same problem, and am documenting the solution for posteriority:)

I've had this problem with GNU screen (the terminal multiplexer), but it can as well happen with a regular terminal. Teddy was right in my case, screen has setguid set.

$ ls -l /usr/bin/screen
-rwxr-sr-x 1 root 84 361016 Mar 30  2011 /usr/bin/screen
      ^

My solution was to save LD_LIBRARY_PATH before execution, and restoring it afterwards. So I created a wrapper ~/bin/screen (put ~/bin on PATH), with the following contents:

#!/bin/bash

# somehow, screen resets LD_LIBRARY_PATH.
# save it here, and restore it in .bashrc
export PRESERVE_LD_LIBRARY_PATH="$LD_LIBRARY_PATH"
/usr/bin/screen "$@"

and then made it executable with chmod +x ~/bin/screen. You might have to open a new shell to get it to pick up the wrapper.

Then I added the following to ~/.bashrc . Remember ~/.bashrc gets sourced every time you start bash, unlike ~/.bash_profile which only gets sourced at login (usually at startup, or when you login over ssh).

if [[ "$PRESERVE_LD_LIBRARY_PATH" != "" ]]; then
    export LD_LIBRARY_PATH="$PRESERVE_LD_LIBRARY_PATH"
    #echo "restored LD_LIBRARY_PATH"
    export -n PRESERVE_LD_LIBRARY_PATH
fi

Now screen (or aterm, xterm, ... just substitute it above) should preserve $LD_LIBRARY_PATH as wanted.

1
  • You can also restore LD_LIBRARY_PATH in .screenrc (instead of .bashrc): setenv LD_LIBRARY_PATH "$PRESERVE_LD_LIBRARY_PATH" followed by unsetenv PRESERVE_LD_LIBRARY_PATH
    – nandhp
    Jul 1, 2013 at 15:06
0

It seems like you have some .bashrc (or equivalent) file in your home directory which defines this variable. I don't know much more details though.

Edit Ok, since starting bash works, I'm guessing not the .bashrc. But maybe some other configuration file which happens to be executed on the same way, when you start xterm or aterm.

1
  • This was my original thought. After much searching there is nothing to be found. I have the benefit of having a very clean (NEW) $HOME.
    – kjfletch
    Aug 21, 2009 at 19:14
0

Most windowing systems recreate the login process when they launch a terminal window, primarily because the terminal window becomes the child of the windowing manager not the launching shell.

So, put it in your .bash_profile or .bashrc if you want it to show up in a new window.

Another alternative is to hand xterm (for example) an argument to run a startup script. Don't exit at the end of that script....

1
  • I will have to resort to this I think. I will probably source my environment variables in both .xinitrc so my window manager has them, and in .bashrc so that my terminal windows will have them.
    – kjfletch
    Aug 22, 2009 at 15:51

You must log in to answer this question.

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