Change /bin/sh link temporarily

Change /bin/sh link temporarily



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.


/bin/sh



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?


/bin/sh


/bin/sh



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


/bin/bash


/bin/sh






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






Possibly of interest: unix.stackexchange.com/questions/468289/…

– ejjl
Sep 11 '18 at 17:21






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


/bin/sh


bash






@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






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




4 Answers
4



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.


unshare



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.



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


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.


/bin/bash


/bin/sh


/bin/bash


/bin/sh


/bin/sh


/bin/sh


/bin/dash


dash


bash


bash


/bin/sh


<<<



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.


/bin/bash


/bin/sh


/bin/sh






LOL. Life can be so simple :-)

– PerlDuck
Sep 11 '18 at 19:08






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






+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


ln


cp -l






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


mount --rbind --make-rslave


cp -r


sudo chroot



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):


/bin/bash


/bin/dash


bash


dash


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.


mount --bind /bin/bash /bin/sh


mount


sh


bash


dash



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



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.






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



Thanks for contributing an answer to Ask Ubuntu!



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)