I wanted to create a jumpbox where the default shell was zsh, but I couldn't actually change the default shell of the users that would be connecting to the box. I also wanted to manage some symlinks in the user profile dynamically with Dotbot.
My initial idea was to add a script to /etc/profile.d
that would just dump users into /bin/zsh
, but this had several different problems, including the all-important question of "But what if I want to run Bash on purpose?"
Through a little bit of trial and error, I settled on this script located at /etc/profile.d/dotbot.sh
# Only run under bash
if [[ $0 == *"bash" ]]; then
# Only for interactive sessions
if [[ $- == *i* ]]; then
# And only for the login session
if shopt -q login_shell; then
if command -v /usr/local/bin/dotbot > /dev/null; then
/usr/local/bin/dotbot -c /srv/dotfiles/dotbot.conf.yaml -q
# Enter zsh
zsh; exit $?
else
>&2 echo "Error: Cannot configure user profile, unable to find Dotbot"
fi
fi
fi
fi
A bunch of nested if
s are always fun:
# Only run under bash
if [[ $0 == *"bash" ]]; then
Early on, I thought I might actually switch the default shell at some point, so this was borne out of a desire for compatibility. The test is written as *"bash"
because the login shell coming from our LDAP is /bin/bash
, whereas my testing of $0
indicated it's just bash
. This was so they'd both work.
# Only for interactive sessions
if [[ $- == *i* ]]; then
Without this step, things like rsync
and scp
would break.
# And only for the login session
if shopt -q login_shell; then
What if you actually need bash
though? This check will always be false except for the top-level shell, so users who are currently in a zsh
session can run bash
without the script dumping them right back into zsh
.
if command -v /usr/local/bin/dotbot > /dev/null; then
/usr/local/bin/dotbot -c /srv/dotfiles/dotbot.conf.yaml -q
# Enter zsh
zsh; exit $?
else
>&2 echo "Error: Cannot configure user profile, unable to find Dotbot"
fi
Check to make sure that dotbot is installed, then start zsh
. The zsh; exit $?
is there to pass exit codes up, but also to ensure that exit
/logout
in the zsh shell actually disconnect the user coming in via SSH. Otherwise they'd exit zsh
and drop into the bash shell that's hosting it.