How can I determine the current shell I am working on?
Would the output of the ps
command alone be sufficient?
How can this be done in different flavors of Unix?
There are three approaches to finding the name of the current shell's executable:
Please note that all three approaches can be fooled if the executable of the shell is /bin/sh
, but it's really a renamed bash
, for example (which frequently happens).
Thus your second question of whether ps
output will do is answered with "not always".
echo $0
- will print the program name... which in the case of the shell is the actual shell.
ps -ef | grep $$ | grep -v grep
- this will look for the current process ID in the list of running processes. Since the current process is the shell, it will be included.
This is not 100% reliable, as you might have other processes whose ps
listing includes the same number as shell's process ID, especially if that ID is a small number (for example, if the shell's PID is "5", you may find processes called "java5" or "perl5" in the same grep
output!). This is the second problem with the "ps" approach, on top of not being able to rely on the shell name.
echo $SHELL
- The path to the current shell is stored as the SHELL
variable for any shell. The caveat for this one is that if you launch a shell explicitly as a subprocess (for example, it's not your login shell), you will get your login shell's value instead. If that's a possibility, use the ps
or $0
approach.
If, however, the executable doesn't match your actual shell (e.g. /bin/sh
is actually bash or ksh), you need heuristics. Here are some environmental variables specific to various shells:
$version
is set on tcsh
$BASH
is set on bash
$shell
(lowercase) is set to actual shell name in csh or tcsh
$ZSH_NAME
is set on zsh
ksh has $PS3
and $PS4
set, whereas the normal Bourne shell (sh
) only has $PS1
and $PS2
set. This generally seems like the hardest to distinguish - the only difference in the entire set of environment variables between sh
and ksh
we have installed on Solaris boxen is $ERRNO
, $FCEDIT
, $LINENO
, $PPID
, $PS3
, $PS4
, $RANDOM
, $SECONDS
, and $TMOUT
.
ps -p $$
as Matthew Slattery points out. For ksh
: echo $KSH_VERSION
or echo ${.sh.version}
. — Jul 24, 2010 at 22:29 echo ${.sh.version}
returns "Bad Substitution". See my solution above — Jul 24, 2010 at 22:41 ps -ef | grep
This is not 100% reliable as Using a simple regular expression via egrep
or grep -e
can easily bring the reliability up to for-all-intents-and-purposes 100%: ps -ef | egrep "^\s*\d+\s+$$\s+"
. The ^
makes sure we're starting from the beginning of the line, the \d+
eats up the UID, the $$
matches the PID, and the \s*
and \s+
account for & ensure whitespace between the other parts. — Mar 05, 2016 at 02:57 ps -ef | awk '$2==pid' pid=$$
— Jan 14, 2017 at 14:18