42

The unix sysadmin where I'm working is reluctant to give me access to change my login shell from ksh to bash. He has given various excuses, the funniest being that since they write all their scripts for ksh they won't work if I try to run them. I don't know where he gets these ideas, but since I can't convince him, is there any alternative that I have?

(chsh is installed on these machines, but we use public/private keypairs for logging in, and I don't have any password, so when chsh prompts me for a password I have nothing to give it. )

iconoclast
  • 9,198
  • 13
  • 57
  • 97
  • What version of Unix are you using? Are you sure all servers have bash? I learned the hard way in AIX not to change your default shell to bash. If the server does not have bash you can not login. – cokedude Apr 22 '21 at 14:59
  • I'm at a different job now, but if I recall correctly these were RedHat boxes. They definitely had bash. It was an IBM shop, to some extent, so they probably also had some old moldy AIX boxes lying around. Perhaps that accounts for the sysadmins using ksh. – iconoclast Apr 22 '21 at 23:57

5 Answers5

75

When you log in, the file ~/.profile is read by the login shell (ksh for you). You can instruct that login shell to replace itself by bash. You should take some precautions:

  • Only replace the login shell if it's interactive. This is important: otherwise, logging in in graphic mode may not work (this is system-dependent: some but not all systems read ~/.profile when logging in through xdm or similar), and idioms such as ssh foo '. ~/.profile; mycommand' will fail.
  • Check that bash is available, so that you can still log in if the executable isn't there for some reason.

You have a choice whether to run bash as a login shell or not. The only major difference in making it a login shell is that it'll load ~/.bash_profile or ~/.profile. So if you run bash as login shell, be very careful to have a ~/.bash_profile or take care not to execute bash recursively from ~/.profile. There is no real advantage of having ~/.profile executed by bash rather than ksh, so I'd recommend not doing it.

Also set the SHELL environment variable to bash, so that programs such as terminal emulators will invoke that shell.

Here's code to switch to bash. Put it at the end of ~/.profile.

case $- in
  *i*)
    # Interactive session. Try switching to bash.
    if [ -z "$BASH" ]; then # do nothing if running under bash already
      bash=$(command -v bash)
      if [ -x "$bash" ]; then
        export SHELL="$bash"
        exec "$bash"
      fi
    fi
esac
  • 19
    Excellent answer! stackexchange needs a Send A Beer button: this would be a time I'd use it. – iconoclast Aug 30 '12 at 13:39
  • Thanks first and. .profile only works for login shell (as OP need). I use Remote Desktop Connection of Windows 10 to login a Linux workstation, then open Terminal in gnome. I want zsh while my sysadmin give me bash. In this case, I have to add the snippet in .bashrc instead of .profile. – Weekend Apr 08 '18 at 12:32
12

This is slightly kludgey, but you can cause bash to be the shell you're using upon login by creating a .profile file in your home directory, containing

SHELL=`type -P bash`
exec bash -l

This will cause the ksh session to be replaced with a bash session. You won't have to type exit (or ^D) twice, as you would if you manually started a new bash session every time you logged in. And typing

echo $SHELL

will even return the path to bash.

iconoclast
  • 9,198
  • 13
  • 57
  • 97
  • 3
    you could of course change $SHELL fairly easily by adding a line to do so before the exec. – derobert Aug 29 '12 at 21:35
  • 2
    If you want the new shell to also be a login shell you should probably exec bash -l. – jw013 Aug 29 '12 at 21:48
  • This is probably the way I would do it as well. – jw013 Aug 29 '12 at 21:48
  • Thanks for the feedback! I've incorporated your improvements into my answer. – iconoclast Aug 29 '12 at 22:02
  • 1
    One last comment: type is recommended over which. – jw013 Aug 29 '12 at 22:06
  • @jw013: good point.... old habits die hard. I instinctively use which and then curse its very existence every time it fails – iconoclast Aug 29 '12 at 22:08
  • Even you can direct run /bin/bash if you have linux box and if you have BSD box you can call direct from /usr/local/bin/bash – PersianGulf Aug 29 '12 at 22:15
  • @seg_fault: sorry, I don't think I followed you. If you mean that I can just type /bin/bash after logging in, then that's exactly the kind of thing I'm trying to avoid. Mostly because I'll usually forget until ksh bites me, and then switching will mean losing the state of my current session. – iconoclast Aug 29 '12 at 22:23
  • @iconoclast i made a lab for you, added jj user and put ksh for it.then with tty2 login with jj.and run bash, many of properties of bash are loaded and many of them not loaded, such as $SHELL show /bin/ksh and HISTSIZE shows 1000 and it's related to bash. – PersianGulf Aug 29 '12 at 22:30
  • 1
    I don't get it! Won't bash also read .profile thus generating an infinite loop? I agree that something along the lines of exec bash is what you want, but you need to make sure you do it only to your login ksh so some if-statements are required! – Bananguin Aug 30 '12 at 06:21
  • 1
    @user1129682 not if there is ~/.bash_profile or ~/.bash_login – Ulrich Dangel Aug 30 '12 at 07:37
  • @UlrichDangel that is a good point - the answer should probably mention that creating either of those files is required to avoid infinite loops using this approach. – jw013 Aug 30 '12 at 14:05
  • --noprofile to prevent infinite loop. actually removing -l worked for me wtf? – kchoi Aug 26 '16 at 20:00
4

Giles' answer should have the -l flag added when executing bash, so that any login profile scripts will be sourced in the new bash shell. (For example anything in /etc/profile.d/ on RHEL). The script should then be:

case $- in
  *i*)
    # Interactive session. Try switching to bash.
    if [ -z "$BASH" ]; then # do nothing if running under bash already
      bash=$(command -v bash)
      if [ -x "$bash" ]; then
        export SHELL="$bash"
        exec "$bash" -l
      fi
    fi
esac
rleelr
  • 181
1

An answer for csh/tcsh inspired by the top voted one by @Gilles is

if ( ! $?BASH ) then
  setenv BASH `command -v bash`
endif

if ( $?prompt ) then
  if ( -x "$BASH" ) then
    exec "$BASH"
  endif
endif
sameers
  • 133
0

Solaris:

usermod -s /bin/bash root