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.

  • 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 – steeldriver Sep 11 '18 at 14:45
  • 2
    Possibly of interest: unix.stackexchange.com/questions/468289/… – ejjl Sep 11 '18 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 '18 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 '18 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 '18 at 7:43
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.

| improve this answer | |
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.

| improve this answer | |
  • 2
    LOL. Life can be so simple :-) – PerlDuck Sep 11 '18 at 19:08
  • 1
    You earned my upvote :) – Joshua Besneatte Sep 11 '18 at 21:35
  • @JoshuaBesneatte Thank you ! Glad you find my answer useful – Sergiy Kolodyazhnyy Sep 12 '18 at 0:38
  • 3
    +1 and it might be better to create hard links instead of copies (via ln or cp -l). – David Foerster Sep 12 '18 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. – Roman Odaisky Sep 12 '18 at 8:34
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.

| improve this answer | |
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.

| improve this answer | |
  • 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 '18 at 16:24
  • I would be interested to see how you would go about preparing the environment. would you use chroot? – Joshua Besneatte Sep 11 '18 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 '18 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? – Joshua Besneatte Sep 11 '18 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 '18 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.