5

I need to call a modified version of a program in /home/user_name/bin rather than the (older) version in /opt/program_name/current on a CentOS 5.3 cluster. The program creates a tcsh script using python and then executes that script.

I can overwrite the PATH to call the modified version of the program in ~/bin, such that which program_name identifies the path to ~/bin. I have done this in .bashrc, .profile, .tcshrc, and .cshrc. However, each time the tcsh is executed, environmental variables from /etc/profile are loaded and the path gets reverted to /opt/program_name/current.

These program-specific variables are set when /etc/profile.d/program_name.sh is called by /etc/profile:

# /etc/profile 
for i in /etc/profile.d/*.sh ; do
    if [ -r "$i" ]; then
        . $i
    fi
done
unset i

Thus, when program_name.sh is called, the corresponding script is:

# /etc/profile.d/program_name.sh
setenv PATH ${PATH}:/opt/program_name/current

How can I prevent /etc/profile from being accessed by my user account?

I do not have su access and other users are still using the older version of the software in /opt/program_name/current so I can't update the software or modify settings in /etc/profile.d/program_name.sh

1

tcsh doesn't spontaneously read /etc/profile, there must be something in the script causing this. A likely possibility (but not the only one) is that the script starts with #!/bin/tcsh -l, so tcsh acts as a login shell. That still won't cause it to read /etc/profile, but it will cause it to read /etc/csh.login, which may read other files (I don't know what CentOS ships in csh.login nor how your system administrators have customized it).

After reading /etc/csh.login, tcsh reads ~/.login. Depending on how it's been configured, it may read ~/.login before, after, or instead of ~/.tcshrc. So be sure to try overriding PATH in ~/.tcshrc as well.

If that doesn't work, modifying the Python script may be your best bet. If the code is in a module, you may be able to work around it by putting a wrapper module in PYTHONPATH that loads the original and makes a few changes.

If that fails, there is no easy way to “redirect” the access the program executable or to tcsh. This is possible in principle by using LD_PRELOAD to wrap around a few file access functions (if all the programs involved are dynamically linked and not set[ug]id), but it's a lot of work.

There may well be an easier way by hooking into the script somewhere, e.g. overriding one of the programs called near the beginning of the script with a function defined in your .cshrc. It's difficult to be more precise without seeing that script.

  • The problem of calling environmental variables when tcsh is invoked appears to be global and not limited to my script. I tried installing a local copy of tcsh in ~/bin/ and I set my PATH in ~/.bashrc ~/.profile ~/.cshrc and ~/.tcshrc to look in ~/bin before /bin. As a result, which tcsh returns /home/user_name/bin/tcsh but when i type tcsh it still loads environmental variables from elsewhere. – David Nov 26 '12 at 16:44
  • @David Run strace -eopen tcsh to see what files it's reading. – Gilles 'SO- stop being evil' Nov 26 '12 at 17:20
  • strace isn't installed on the Cluster. When I run strace -eopen tcsh on the head node I get back the paths I expect. In fact, tcsh behaves as expected when I initially log into the head node. I think that connecting to the Sun Grid Cluster nodes is pulling global variables from /etc/csh.cshrc. I can't find the setenv variables specified elsewhere. /etc/csh.cshrc executes /etc/profile.d/*.csh which contains the program-specific setenv PATH ${PATH}:/opt/program_name/current calls. These variables are set every time tcsh is called, overwriting my $PATH. – David Nov 27 '12 at 0:20
0

Your best bet is probably to not rely on PATH but instead give the full path to program_name.

As for why it's sourcing /etc/profile, it must be called by either /etc/csh.chsrc or possibly /etc/csh.login. For more info, see the man page for tcsh. Specifically, look (search) for the sections Startup and shutdown and FILES in the man page.

From Startup and shutdown, this is the most relevant part:

A login shell begins by executing commands from the system files /etc/csh.cshrc and /etc/csh.login/. It then executes commands from files in the user's home directory

...

Non-login shells read only /etc/csh.cshrc and ~/.tcshrc or ~/.cshrc on startup.

And from FILES (which covers all *nix flavors):

   /etc/csh.cshrc  Read first by every shell.  ConvexOS, Stellix and Intel
                   use /etc/cshrc and  NeXTs  use  /etc/cshrc.std.   A/UX,
                   AMIX,  Cray  and IRIX have no equivalent in csh(1), but
                   read this file in tcsh anyway.  Solaris  2.x  does  not
                   have it either, but tcsh reads /etc/.cshrc.  (+)
   /etc/csh.login  Read  by  login shells after /etc/csh.cshrc.  ConvexOS,
                   Stellix   and   Intel   use   /etc/login,   NeXTs   use
                   /etc/login.std,  Solaris 2.x uses /etc/.login and A/UX,
                   AMIX, Cray and IRIX use /etc/cshrc.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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