9

I have a piece of software that requires /bin/sh to be Bash, but for Ubuntu the default is Dash and I want to keep it the default; I don't want to change it to Bash permanently.

Is there a way to change it only for a running terminal session? So a program running in this terminal will see /bin/sh linked to bash but the rest of the system will still see Dash? Or can I trick the software to see /bin/sh as Bash even if its not?

I didn't write this software and hacking it to use /bin/bash instead of /bin/sh is not really an option.

8
  • 2
    You can change it temporarily - but not (AFAIK) limit the scope to a single terminal session. See for example /bin/sh is a symbolic link that doesn't point to /bin/bash Sep 11, 2018 at 14:45
  • 2
    Possibly of interest: unix.stackexchange.com/questions/468289/…
    – ejjl
    Sep 11, 2018 at 17:21
  • 7
    Whatever you do, please also report this as a bug for the software in question. Because assuming /bin/sh is bash is a bug, and it causes actual problems (as you're finding out). If no one complains, it may never get changed.
    – marcelm
    Sep 11, 2018 at 22:38
  • 1
    @SergiyKolodyazhnyy If the bug doesn't cause problems on the only platform(s) they support, then they can probably get away with it. It's still a bug though.
    – marcelm
    Sep 12, 2018 at 10:30
  • 1
    The software is Petalinux released by a "small" company called Xilinx, and according to the documentation Ubuntu 16.04 is supported (along with CentOS and RHEL), so I would say its a bug.
    – corwin
    Sep 13, 2018 at 7:43

4 Answers 4

14

If it's a script, just call the script as

bash scriptname.sh

No need to change links at all.

For compiled executable you can go chroot route:

mkdir rootfs
cp -a /usr rootfs/
cp -a /lib rootfs/
cp -a /lib64 rootfs/
cp /bin/bash  rootfs/bin/sh
cp yourprogram  rootfs/
sudo chroot rootfs  sh

And then run your program or sudo chroot rootfs /yourprogram


However, in practice there is no reason why you can't use /bin/bash as a symlink to /bin/sh. In fact, prior to version 6.10 Ubuntu was using /bin/bash as /bin/sh, and then they switched due to /bin/sh being a much faster, leaner implementation of POSIX /bin/sh (that is, it adheres to the POSIX standard for how Unix-like operating system utilities and OS should behave and implement some of their internals), and due to portability reasons. I strongly recommend reading Gilles' answer as well for historical notes on how /bin/dash came about. As for compatibility, scripts written for dash using POSIX features will run with bash being a default shell perfectly fine. Usually, it's the other way around that causes problems - bash has features that aren't required by /bin/sh, like the <<< syntax or arrays.

Additionally, the command in question is probably written with RHEL or CentOS in mind, which does use /bin/bash as a symlink to /bin/sh, suggests two things: they probably targeted specific OS and didn't adhere to POSIX principles. In that case, it would also be a good idea to check what other things the command requires, since if it's really written with another OS in mind, you might run into more problems than just re-linking /bin/sh.

7
  • 2
    LOL. Life can be so simple :-)
    – PerlDuck
    Sep 11, 2018 at 19:08
  • 1
    You earned my upvote :) Sep 11, 2018 at 21:35
  • @JoshuaBesneatte Thank you ! Glad you find my answer useful Sep 12, 2018 at 0:38
  • 3
    +1 and it might be better to create hard links instead of copies (via ln or cp -l). Sep 12, 2018 at 8:10
  • 1
    Consider mount --rbind --make-rslave rather than cp -r. Can be made read-only as well. Also sudo chroot runs the script as root which might not be optimal. Sep 12, 2018 at 8:34
10

Two answers already suggest chrooting and bind mounts, and there's a third, closely related option: mount namespaces. Using the unshare program, you can create a new mount namespace, and mounts within this namespace won't affect other namespaces.

For example, in one terminal, I do:

muru|[0] ~ sudo unshare -m /bin/bash
root@muru-1604:~# sudo mount --bind /bin/bash /bin/sh
root@muru-1604:~# /bin/sh --version
GNU bash, version 4.4.18(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
root@muru-1604:~# sudo -iu muru
muru|[0] ~ /bin/sh --version  # propagates
GNU bash, version 4.4.18(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

And in another:

$ /bin/sh --version
/bin/sh: 0: Illegal option --

So you could run this inflexible program in its own mount namespace.

5

One possibility would be a bind mount of a single file. To do this, you mount the file /bin/bash just over /bin/dash so bash sort of covers or hides dash. Here are the steps (including the reverse):

root@myhost:~# cd /bin

# situation before (bash and dash are different):
root@myhost:/bin# ls -l *sh*
-rwxr-xr-x 1 root root 1113504 Apr  4 20:30 bash
-rwxr-xr-x 1 root root  121432 Jan 25  2018 dash
lrwxrwxrwx 1 root root       4 Jul 13 11:38 sh -> dash
...

# mount /bin/bash over /bin/dash:
root@myhost:/bin# mount --bind /bin/bash /bin/dash

# situation now (bash and dash are the same):
root@myhost:/bin# ls -l *sh*
-rwxr-xr-x 1 root root 1113504 Apr  4 20:30 bash
-rwxr-xr-x 1 root root 1113504 Apr  4 20:30 dash
lrwxrwxrwx 1 root root       4 Jul 13 11:38 sh -> dash
...

# Now everything that runs `/bin/sh` in fact uses `/bin/bash`.

# check what the symlink "sh" says:
root@myhost:/bin# sh --version
GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
...

# undo the mount:
root@myhost:/bin# umount /bin/dash 

# situation now (bash and dash are different again):
root@myhost:/bin# ls -l *sh*
-rwxr-xr-x 1 root root 1113504 Apr  4 20:30 bash
-rwxr-xr-x 1 root root  121432 Jan 25  2018 dash
lrwxrwxrwx 1 root root       4 Jul 13 11:38 sh -> dash
...

# check what the symlink "sh" now says:
root@myhost:/bin# sh --version
sh: 0: Illegal option --

I didn't try to mount --bind /bin/bash /bin/sh to directly hide the symlink, though. The above mount trick just makes bash and dash identical so that sh refers to bash although it points to dash. Also, this is a system-wide solution, not only for the current terminal window.


I must confess, this might be overkill and simply changing the symlink temporarily is far easier. I just wanted to show another possible way.

1

You should be able to change it for just the current session by using an alias. Before running your command in the terminal:

alias sh=bash

This will be temporary and only active in the terminal it was executed from.

HOWEVER: This will NOT WORK if your script uses absolute paths.

Good idea as such, but if the software directly calls /bin/sh with an explicit pathname, it will not work. Anyway, that software does not seem to be very properly designed making such assumptions. I would probably run it from a script that prepares and resets the proper environment if I had to use it at all. – vanadium

Unfortunately, "hacking" the script might be your only option. Per convo with @vanadium, you could create a wrapper script like this:

#!/bin/bash
sudo ln -sf /bin/bash /bin/sh
/run/my/script
sudo ln -sf /bin/dash /bin/sh

However, during the duration of your script, you better hope nothing on your system explicitly requires dash.

5
  • 3
    Good idea as such, but if the software directly calls /bin/sh with an explicit pathname, it will not work. Anyway, that software does not seem to be very properly designed making such assumptions. I would probably run it from a script that prepares and resets the proper environment if I had to use it at all.
    – vanadium
    Sep 11, 2018 at 16:24
  • I would be interested to see how you would go about preparing the environment. would you use chroot? Sep 11, 2018 at 16:34
  • I did not have such ambitious ideas. I was just thinking of a script that would temporarily have sh link to bash and reset when done. The main problem in this question is with the "piece of software" concerned, I think.
    – vanadium
    Sep 11, 2018 at 17:17
  • what would happen if something else needed dash whilst the symbolic link was moved.... something like ln -sf /bin/bash /bin/sh at the begginning and ln -sf /bin/dash /bin/sh when done? Sep 11, 2018 at 17:23
  • Most other processes probably will happily use bash instead of dash if the link is changed. Yes, in that vain, but to mimic the current situation, I would make relative links, i.e. "cd /bin ; ln -sf bash sh", but that is probably a purist detail that won't matter in practice.
    – vanadium
    Sep 11, 2018 at 17:27

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.