13

I'm running a fresh Oneiric install (i.e. not an upgrade) on two different systems and running into the same set of seemingly related problems.

The most frustrating of the bunch is that, when I use the .profile and .bashrc that I have carried with me from Mac OS X, logging in to X via LightDM logs me out immediately. I believe this is caused by the fact that, when running "/bin/sh", it behaves as /bin/dash, but still has the $SHELL variable set to /bin/bash.

Extrapolation

I have a huge .bashrc. You can see it here if you want, but its contents are probably not relevant, aside from the fact that it's full of bashisms, and the fact that it works with no errors inside xterm or on a virtual console.

My .profile looks like this (abbreviated):

case $SHELL in 
*bash*)
    if [ -f $HOME/.bashrc -a -r $HOME/.bashrc ]; then
        . $HOME/.bashrc
    fi
    ;;
esac

If I attempt to log in to X via LightDM, it will log me immediately back out. I get errors in .xsession-errors relating to my .bashrc that look like this (abbreviated):

/home/mrled/.bashrc: 103: [[: not found
[: 103: Linux: unexpected operator
[: 274: -P :: unexpected operator
/home/mrled/.bashrc: 520: complete: not found

As I said, when I run bash from a virtual console, I don't get these errors. Furthermore, if I remove my .profile, I can log in to X just fine. (I can also log in to a virtual console and use startx to initiate an X session that works, but this is of course not a long term solution.)

However, I discovered that if I run /bin/sh -l, I do get the errors. Here's an example session (note: the bash prompt I have simplified to bash>, and the sh prompt is just $):

bash> echo $SHELL
/bin/bash
bash> echo $BASH_VERSION
4.2.10(1)-release
bash> /bin/sh -l
/home/mrled/.bashrc: 103: [[: not found
[: 103: Linux: unexpected operator
[: 274: -P :: unexpected operator
/home/mrled/.bashrc: 520: complete: not found
$ echo $SHELL
/bin/bash
$ echo $BASH_VERSION

$

Q1: Why is this happening?

I understand that /bin/sh now points to dash rather than bash, but if that's true, then why is $SHELL still returning /bin/bash?

Q2: What can I do to work around it?

Is there a way to work around this? I want to keep my profile loading .bashrc so that I get the same environment on both login and non-login shells, but obviously I only want it to load for bash itself, not /bin/sh masquerading as bash.

You may have noticed the difference in the contents of the $BASH_VERSION variables above. I have tried wrapping my .profile in something like this:

if [ -n $BASH_VERSION ]; then
    # the rest of my .profile as above
fi

The -n test should return true only if the length of the string is non-zero, however, even though in the session above, when I'm running under /bin/sh -l it returns an empty string for $BASH_VERSION, when it's included in my .profile like this, it passes the test! It them proceeds to source my .bashrc and give me the same errors as before.

Now I'm really confused.

4
  • Note that dash -l also shows $SHELL having the value /bin/bash. Jan 22, 2012 at 8:16
  • 3
    $SHELL is whatever the last field in /etc/passwd (or getent passwd) says. Jan 22, 2012 at 15:53
  • @DennisWilliamson Thank you, that's what I needed to know to find the right answer. Jan 23, 2012 at 18:39
  • You're doing it wrong. You should put non-bash-specific environment in ~/.profile, bash-specific things in ~/.bashrc, and have ~/.bash_profile source both.
    – nyuszika7h
    Mar 22, 2015 at 15:59

3 Answers 3

12

You can make the fact that $BASH_VERSION is blank in dash work for you:

if [ "$BASH_VERSION" = '' ]; then
    echo "This is dash."
else
    echo "This is bash."
fi
3
  • 2
    The "x" technique is archaic and only needed in ancient shells. Use if [ "$BASH_VERSION" = '' ] Jan 24, 2012 at 19:23
  • @DennisWilliamson: Thanks. I had thought your technique was specific to Bash, but I just rested it in Dash and it worked. I've edited my answer. Jan 25, 2012 at 4:40
  • Or just use -n, or nothing. (+1, though. = '' works perfectly well.) Aug 31, 2017 at 18:26
5

You just have to use quotes on the variable BASH_VERSION to use -n

if [ -n "$BASH_VERSION" ];then
 echo "this is bash"; 
else 
 echo "this is dash";
fi
1
  • 1
    since [ "$EMPTY_STRING" ] evaluates false, you don't even need the -n. You just have to quote the variable.
    – jeberle
    Mar 11, 2016 at 17:22
2

Use /proc/[PID]/cmdline to see what the script is being run with and test for what it contains. The $$ variable will give us the PID of the running shell. Thus we can make a script like this,

#!/bin/bash
if grep -q 'bash' /proc/$$/cmdline ;
then
    echo "This is bash"
else
    echo "This is some other shell"
fi

Here's a test of the same script:

$> bash test_script.sh                                                                                                
This is bash
$> dash test_script.sh                                                                                                
This is some other shell
5
  • This will not work on Mac. Check $BASH_VERSION. Jun 27, 2016 at 12:49
  • 2
    @AustinBurk it doesn't need to work on Mac. This is Ask Ubuntu. Jun 27, 2016 at 20:03
  • @Zacharee1 oh darn it, I wasn't paying attention :,) Jun 27, 2016 at 20:19
  • I don't want to edit this away from what you intend, but I suggest mentioning this method's limitations. Bash needn't have bash in its name; it's not uncommon for the bash executable to be run through a symlink with another name. Usually one would still want to consider that Bash. Also, the pattern is matched anywhere in /proc/$$/cmdline, which should be possible to fix, but keep in mind that arguments in cmdline are null-character delimited. grep -qE '(^|/)bash$' feels like it should work but gives a false positive when any argument is bash. Aug 31, 2017 at 18:24
  • @EliahKagan Feel free to edit my answers any time - you've sufficient expertise so I know your edits can offer only improvements. The answer was written when I was much greener with shells than I am now. Sep 17, 2017 at 18:30

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.