When you run a shell within your login shell, $SHELL is still your login shell. When you run another shell within that shell, $SHELL still stays the same. There are some bad scripts the behavior of which incorrectly depends on $SHELL. If you want to run Bash, you might want $SHELL to stay /bin/bash
.
And sometimes you want to login to a version of Bash not from /etc/shells
— like, from somewhere else in the system or even from your home directory.
I'm not sure if there is any non-shell-specific standard way of getting the path of your childmost shell executable. In Bash you can get it from $BASH.
If you want to land in /bin/bash
only if your own bash
binary doesn't get found in $PATH, put this in your .bashrc
:
(return $NO_FURTHER_PLEASE) && [[ $BASH == "/bin/bash" ]] && { NO_FURTHER_PLEASE=1 bash; exit $?; }
You might want to replace "/bin/bash"
for $SHELL
in the above if you are not sure if your login shell will stay /bin/bash
since $SHELL
will be always your login shell from /etc/shells.
If you also want to land in /bin/bash
wherever it is already Bash 5 or newer, put this instead:
(return $NO_FURTHER_PLEASE) && [ "${BASH_VERSINFO:-0}" -le 4 ] && { NO_FURTHER_PLEASE=1 bash; exit $?; }
Note that in both cases if the bash
from $PATH
ends up being /bin/bash
, you get /bin/bash
inside /bin/bash
. That could be improved on by re-checking against the original condition with something like
((return $NO_FURTHER_PLEASE) || [ the condition goes there ]) && (exit 2)
or instead, even better,
(return $NO_FURTHER_PLEASE) && [[ $SHELL == $BASH ]] && (exit 2)
Of course, one could just hardcode the absolute path of their bash
in .bashrc
and then there would be no such problem.
If someone is wondering, no, $NO_FURTHER_PLEASE
is not inherited by any bash
that you choose to run inside your bash
since NO_FURTHER_PLEASE
is not exported.
Yes yes i know that there is probably a neater way to test against a variable than returning it from a subshell, i am just too lazy to look for it.
Edit
It seems like all of the above could be replaced with just
FURTHER_BASH=$(type -p bash)
if [[ $SHELL != $BASH ]]
then
unset FURTHER_BASH
elif [[ $BASH != $FURTHER_BASH ]]
then
$FURTHER_BASH
exit $?
else
unset FURTHER_BASH
echo "Staying in login shell." >&2
fi
[ "${BASH_VERSINFO:-0}" -le 4 ] && {
echo "Warning: Staying in bash version $BASH_VERSINFO < 5."
(exit 2)
}
Top comments (0)