Which Behavior?



  • Our "back-end" processing system runs on UNIX - Solaris to be exact. I'm not unfamiliar with UNIXes; been working with them on/off since 1994-ish. Solaris, AIX, HPUX, Linux ... I've messed with them all. Today, my system administrator brought me some news about the problem I've been having (or thought I'd been having) for the past week.

    History:

    We have tons of environment scripts. We have environment scripts written for adding Oracle stuff to the environment. We have environment scripts for adding ${APPLICATION} to the environment. We have environment scripts to add Java to the environment. We have scripts that add development tools to the environment (such as SQL Developer, NetBeans, etc.) Basically, if there's something that needs to be in place, we add it to the environment.

    At login. To make it simple, everyone has the same environment (yes, users, programmers, engineers, DBAs.) And the default shell is c-shell (csh.)

    So everyone has (at least) a .cshrc file in their home directory to bring all this stuff in.

    However, as a sane person, I asked the question: "Is csh required?"

    "Well, no, not as such, but stuff won't run right if you don't use the environment we set up."

    "Right, but if I assume the risk and want to make my own way, I can use, say, something sane like, oh, I dunno, bash?"

    "I guess."

    So, I asked the admin to change my default shell to bash. And I've been pretty happy about that choice. If I ever NEED the everything-in-it environment, I can temporarily drop down to csh and its all there.

    Well, we've been doing some interesting moving forward (moving from Java 1.6r13 to Java 1.7rLatest **, doing more automation, etc.) and I've been trying to compile a NetBeans project at the command-line with ant (think 'make' but more Java-specific.) The 'default' version of ant, in the everything environment was built around the turn-of-the-century and didn't support things like includes (or imports, I can't recall the keyword right now.)

    So I try to remove the old ant from PATH and set it and ANT_HOME to the NetBeans' ant modules. Still, not working right. Hrm. I check PATH. I check ANT_HOME. Both correct. I then use the UNIX which command which is supposed to tell you where the program you're running is located.

    bash% which ant
    ant:    aliased to ant.csh !*

    Huh. That's weird. I check my .bashrc and .bash_login files for any aliases. Other than a couple for vim (vi editor), I have none. Odd. I check with the shell to see what aliases I have.

    bash% alias
    alias vi='/opt/SUNWspro/contrib/vim/bin/vim '
    alias vim='/opt/SUNWspro/contrib/vim/bin/gvim '

    Huh. Odder still; no alias for ant according to the shell itself. Well, let me try to unalias it anyhow.

    bash% unalias ant
    -bash: unalias: ant: not found

    Okay, so, not surprising based on what I can see, but still.  Where is this alias coming from? I poked into /etc files to see if I could see anything. I put print statements in the scripts to figure out where/when the ant alias was showing up. It was driving me crazy.

    Finally, today, I'd had enough and went to the sysadmin. He's like "told you so" about the environment ... :sigh: ... anyhow, I press him on the issue: where am I getting this alias from and how do I get rid of it? Well, this intrigued him. He started poking around. Hrm, its not just you, but anyone with a bash shell gets that alias too. Root doesn't. Hrm ...

    After about 5 minutes of watching over his shoulder, I got bored and told him to let me know what he finds.

    After about 20 minutes or so, he comes to me. "Its coming from your .cshrc file."

    I'm like whaaaat? How?

    Then he drops the bomb. Apparently, the behavior of the which command is not what I thought -- it scans your csh environment by invoking a c-shell, importing all those environment settings, to see what the csh environment looks like, looking specifically for paths and aliases. Even when not using c-shell or when c-shell is not your default shell. This is the behavior.

    Thanks, Sun/Oracle.

    The question remains, however: How does which work as I expect it to when I hide my .cshrc file -- finding stuff on the path?


    * I don't have access to a Linux box here ... this isn't the behavior in the GNU version(s) of which, is it?

    ** I'm quite concerned about this as there are NUMEROUS workarounds in the code to make stuff work, some around specific actually documented 'bugs' in Java/JVM of the day. Moving to a new version of Java broke our code in not-too-obvious ways a year and a half back and I'm concerned that a major revision going from 1.6r13 to the latest 1.7 might turn out to have undetectable bugs and such ... since a lot of exception handlers swallow and continue.

     



  • The Debian which(1) doesn't even attempt to stat a .cshrc file, let alone open one. Similarly, it doesn't try to invoke csh.



  • Have you tried "which which" in both shells to find out which which is which?

    Some shells alias "which" to "whence -v", so could interpret your command line differently.

    I know "which" scans aliases first, then $PATH, allowing a command to be used within its own alias (alias rm="rm -i" crap).

    Spawning a csh then sourcing your .csh during the search for the command target is a bit WTFy and a new one on me, but then I dislike the csh so aren't overly familiar with it. 



  • @zelmak said:

    After about 20 minutes or so, he comes to me. "Its coming from your .cshrc file."

    I don't know how it is on Linux exactly, but on all pre-Linux unixes I've ever seen, "which" is an external command, usually a shell script, sometimes even a [i]csh script[/i] (gasp!), that tries to guess what your shell is going to use for a particular command, and prints this guess.

    That makes "which" pretty worthless, especially for bash users, but that's not surprising because "which" is actually a workaround for a shortcoming of csh, and you don't need it if you use bash (or any bourne-shell derivative).

    The command you are looking for is "type": this is a shell built-in, and it tells you exactly what the shell will execute for a given command name. Works on bash and /bin/sh, and every bourne-shell derivative that I've ever seen.

    Oh, and TRWTF is csh.



  • @Planar said:

    I don't know how it is on Linux exactly, but on all pre-Linux unixes I've ever seen, "which" is an external command, usually a shell script, sometimes even a csh script (gasp!), that tries to guess what your shell is going to use for a particular command, and prints this guess.
     

    That was my understanding - but a quick test:

    [ cassidy@linuxbox ] $ which which
    alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
            /usr/bin/which

    [ cassidy@linuxbox ] $ csh
    % which which
    which: shell built-in command.

    Interesting - different behaviour between shells.



  • @Cassidy said:

    Have you tried "which which" in both shells to find out which which is which?


    If two witches watched two watches, which witch would watch which watch?



  • @Cassidy said:

    [ cassidy@linuxbox ] $ which which
    alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
            /usr/bin/which

    [ cassidy@linuxbox ] $ csh
    % which which
    which: shell built-in command.

     

    Meanwhile, in Debian Stable...

    Bash:

    feldspato:~$ :) which which
    /usr/bin/which 

    Csh

    % which which
    which: shell built-in command.


     @Cassidy said:

    Interesting - different behaviour between shells.

    Well, that's to be expected.

     



  • @Mcoder said:

    @Cassidy said:

    [ cassidy@linuxbox ] $ which which
    alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
            /usr/bin/which

    [ cassidy@linuxbox ] $ csh
    % which which
    which: shell built-in command.

     

    Meanwhile, in Debian Stable...

    Bash:

    feldspato:~$ :) which which
    /usr/bin/which 

    Csh

    % which which
    which: shell built-in command.


     @Cassidy said:

    Interesting - different behaviour between shells.

    Well, that's to be expected.

     


    Fedora 18: Spherical Cow

    ben@loads ~$ which which
    alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
    	/usr/bin/alias
    	/usr/bin/which
    ben@loads ~$ csh
    bash: csh: command not found
    ben@loads ~$ zsh
    [ben@loads]~% which which
    which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
    	/usr/bin/alias
    	/usr/bin/which
    


  • @Mcoder said:

     @Cassidy said:

    Interesting - different behaviour between shells.

    Well, that's to be expected.

     

    Well, I didn't expect an OS command to actually be a shell builtin then work differently (I'd still expect "cat" and "ls" to work identically between shells)... but then thinking about it, I have encountered this before:

    "enable" is a printer command under Solaris and worked fine until the bash came along, requiring people to use "/usr/bin/enable" to bypass the builtin.

     



  • @Cassidy said:

    Well, I didn't expect an OS command to actually be a shell builtin then work differently
     

    Some bash builtins:

    cd, echo, logout, source (AKA '.')

    alias and unalias (I had a WTF moment reading Ben L's post, which tries hard to find an executable, it's probably wrong on that case.)

    test (AKA '[', or the thing that every script uses to test the environment or filesystem)

    [[, and ((

    if, while and for

    And the list goes on and on...



  • @Mcoder said:

    Some bash builtins:

    cd, echo,

     

    Not on my bash. "which" claims it's /bin/echo.

    I ain't inclined to completely believe it.

     



  • @Cassidy said:

    Not on my bash. "which" claims it's /bin/echo.
    which isn't a bash built-in, so it can't tell you about built-ins. Use type echo instead.



  • @ender said:

    which isn't a bash built-in
     

    Doh, you're right. Just so used to using it from ksh days.


Log in to reply