7

I am trying to determine the location of bash interpreter on my Solaris system and I am a bit confused. When I type:

echo $SHELL

The resulting path is:

/bin/bash

And when I type:

which bash

I get:

/usr/bin/bash

Can anyone please explain this discrepancy?

Eugene S
  • 3,484

6 Answers6

10

Your system probably has bash installed in multiple locations, whether as different versions of bash or just symbolic links.

which is not really a useful command for most purposes - it's not really portable or very usable in scripts. In general, type is better. The idea behind which is to do a PATH search for the command you give it as an argument.

$SHELL does not necessarily reflect the currently running shell. Instead, $SHELL is the user's preferred shell, which is typically the one set in /etc/passwd. If you start a different shell after logging in, you can not necessarily expect $SHELL to match the current shell anymore.

As you can see, $SHELL and which are completely unrelated. Neither of these will tell you what shell you are actually running.

A side note: Unfortunately, matching the shell you are currently running to a location in the filesystem is harder than one might think. This is because binaries are loaded into memory in order to run, and in most systems the copy in memory will continue to run fine even after you delete the original from disk (the kernel may keep the disk copy around in "limbo" until it is really no longer needed). I don't think there is any portable way to go about this - you'd have to resort to platform specific methods. For example, on Linux, examining the link /proc/$$/exe should give you a decent idea of what file is running (where $$ is the process ID of your running shell). Unfortunately I am not familiar with Solaris, so I can't help you there.

jw013
  • 51,212
9

The other answers are good, but I like to give a demonstration.

% echo $SHELL
/bin/zsh
% which bash
/bin/bash
  • The first command tells me which shell will be executed by login when you log in. In my case, /bin/zsh.
  • The second command tells me the first occurrence in my $PATH the bash command can be found.

One does not imply the second, nor vice versa.

I'm not going to restate other people's answers but in addition to that I want to point out some things.

  • The default shell on Solaris is /bin/bash
  • On Solaris /bin is a symlink to ./usr/bin
  • The default $PATH on Solaris is /usr/bin:/bin

That's why you're seeing this behavior.

bahamat
  • 39,666
  • 4
  • 75
  • 104
  • 2
    The first command shows your default shell, which may be the shell you are currently running, but not always. – jordanm Jul 19 '12 at 18:06
  • @jordanm: ah, yes you're right. Fixing. – bahamat Jul 19 '12 at 18:11
  • 1
    The default shell is /usr/bin/bash only on Solaris 11. Under Solaris 10 and older it is /bin/sh which is the legacy Bourne shell implementation. Since Solaris 11, /bin/sh is ksh93. Solaris default PATH for non root users is just /usr/bin, having both /usr/bin and /bin would make no sense. – jlliagre Jul 19 '12 at 23:29
  • @jlliagre: You're right regarding S10/S11. About /bin/ and /usr/bin I agree it doesn't make sense, but if you don't have a PATH declared that's what the system gives you. – bahamat Jul 20 '12 at 00:04
  • The PATH is always defined by default on Solaris unless you mess with configuration files. It is set on Solaris 11 to /usr/bin for regular users and /usr/bin:/usr/sbin for root. The default (and redundant) PATH set by bash if unset at launchtime is /usr/gnu/bin:/bin:/usr/bin:/sbin:/usr/sbin:. This is perhaps where you observe /bin:/usr/bin. – jlliagre Jul 20 '12 at 01:13
  • 1
    I just did it on Solaris 11 and reported exactly what I got. – bahamat Jul 20 '12 at 03:07
1

echo $SHELL shows the value of the SHELL environment variable. This is a user configuration, which you can set to the path to your favorite interactive shell. Many programs invoke $SHELL when asked to invoke a shell.

I think all shells leave this variable alone unless it is unset when they start. Bash sets SHELL to its own path if the variable is unset when it starts. ATT ksh93 sets SHELL to /bin/sh if unset (even if /bin/sh is some unrelated shell). Ksh (all versions) checks whether SHELL is rsh when it starts; if it is, it starts as a restricted shell.

which bash shows the path to the bash executable (except when it doesn't — you should use type bash instead). More precisely, it searches the directories in $PATH for an executable called bash.

echo $0, in an interactive shell, shows the command name that was used to invoke the shell.

ps $$ (typed from a shell) displays information about the shell process ($$ is expanded to the process ID of the shell).

ls -l /proc/$$/exe shows the full path to the executable for the shell

For example, my favorite shell is zsh, but here I've just started a home-compiled version of bash that isn't in the $PATH.

% ./bash
$ echo $SHELL
/bin/zsh4
$ type bash
bash is /usr/bin/bash
$ echo $0
./bash
$ readlink /proc/$$/exe
/home/gilles/src/bash-git/bash
$ pwd
/home/gilles/src/bash-git
$ rm bash
$ echo $0
./bash
$ readlink /proc/$$/exe
/home/gilles/src/bash-git/bash (deleted)
0

$SHELL is an environment variable set with the path to the current login shell, which in this case is bash. If you were to use the chsh command to switch to some other shell (e.g. zsh), then you would see /bin/zsh when you ran echo $SHELL.

The which command actually has nothing to do with a specific shell, other than being responsible for determining which program would be run if you were to call that program directly. You might have several versions of that program in the paths in your $PATH variable that could be run. The reason you see /bin/bash when you run which bash is because that's where the system first finds the bash program in the hierarchy that is $PATH.

You can run which on any command, not just a shell.

kenny
  • 1,453
0

The which command searches through directories specified in your $PATH variable and returns the first match it finds as this will be the file which will be executed.

$SHELL returns the canonical name of the file currently running, e.g., /bin/bash. /usr/bin/bash is probably a link to /bin/bash anyway. Use $SHELL to find the name of your current command interpreter.

bahamat
  • 39,666
  • 4
  • 75
  • 104
StarNamer
  • 3,162
  • It's not the file currently running, it's the default shell. See other answers. Also, for what it's worth, I think the symlink is the other way around on Solaris. – Mikel Jul 19 '12 at 18:52
  • 1
    More precisely, /bin/bash and /usr/bin/bash are the very same file, /bin being a symbolic link to /usr/bin. – jlliagre Jul 20 '12 at 08:40
  • I stand corrected. $SHELL is the user's default shell, not the currently running one. – StarNamer Jul 20 '12 at 15:36
  • Regarding other answers about which and type by @Gilles and @jw013, when using the tcsh shell, which is a builtin command and type is not found. Conclusions: (1) You should know the shell you are running before you enter a command. (2) You should always put #!/bin/bash (or whatever is needed) at the top of scripts. – StarNamer Jul 20 '12 at 16:05
0

Under Solaris, one simple way to know what shell you are running and what launched it is ptree, here my shell is ksh:

$ ptree $$
408   /usr/lib/ssh/sshd
  1131  /usr/lib/ssh/sshd
    1132  /usr/lib/ssh/sshd
      1142  -ksh
        1146  ptree 1142

The standard way to get what a command will actually run is to use the type command.

$ type bash
bash is /usr/bin/bash

Given the fact /bin and /usr/bin are interchangeable under Solaris (and this is a trend on other Unix like OSes too), whether type bash will return /bin/bash or /usr/bin/bash depends only on what first appears on your PATH and anyway doesn't matter that much.

jlliagre
  • 61,204