Making zsh default shell without root access

Create .bash_profile in your home directory and add these lines:

export SHELL=/bin/zsh
exec /bin/zsh -l

Update: .profile may work as a general solution when default shell is not bash. I'm not sure if .profile may be called by Zsh as well that it could go redundant but we can do it safely with a simple check:

export SHELL=/bin/zsh
[ -z "$ZSH_VERSION" ] && exec /bin/zsh -l

We can also use which to get the dynamic path of zsh which relies on the value of $PATH:

export SHELL=`which zsh`
[ -z "$ZSH_VERSION" ] && exec "$SHELL" -l

Normally you can use chsh as a non-root user. But it's occasionally disabled, usually in sites that use some form of networked user database like NIS and LDAP. There might be a ypchsh (NIS) or chsh.ldap (LDAP) instead.

chsh will also usually allow only some approved shells, typically the ones listed in /etc/shells.

If you can't use chsh or its variants at your site, then arrange for your login shell to exec your favorite shell, and set the SHELL variable to point to your favourite shell.

  • If your login shell is sh, dash or ksh: the file you need to edit is ~/.profile. Beware that this file is read at the beginning of an interactive session as well as by some non-interactive session startup scripts (e.g. for X11 sessions), so you need to take care: only call exec (which replaces the current process) when the current shell is interactive. Except for the Bourne shell (the /bin/sh of Solaris 10 and before), you can tell that a shell is interactive by the presence of i in the option list ($-).

    preferred_shell=
    if [ -x /bin/zsh ]; then
      preferred_shell=/bin/zsh
    fi
    …
    if [ -n "$preferred_shell" ]; then
      case $- in
        *i*) SHELL=$preferred_shell; export SHELL; exec "$preferred_shell";;
      esac
    fi
    

    If you want zsh to read your .zprofile, pass the -l option.

  • If your login shell is bash, you can proceed as above. Alternatively, you may put these commands in ~/.bash_profile. Most session startup scripts only read ~/.profile and not ~/.bash_profile, but I've seen some that run under bash and read .bash_profile, so even there you should be careful not to call exec in a non-interactive shell.

  • If your login shell is csh or tcsh, see an example in Changing the default shell without chsh or administrator priviledges


If you can't run chsh because you don't have admin privileges, talk to someone who does.

Most likely you can't use chsh as non-root because the system you're using is configured so that chsh wouldn't work, for example because the system uses NIS or LDAP rather than just the /etc/passwd file. Or perhaps your system's administrator just wants to maintain some control.

The procedure for changing your shell depends on your organization's policies. There may be a local command that does what chsh normally does. Or you may need to submit a support ticket requesting a shell change.

Most of the other answers are good, but if your administrators are reasonably responsive you might not want to bother hacking your startup scripts. I'd probably just invoke zsh -l manually after logging in until the administrator gets around to updating my account.

Another thing to keep in mind: Sometimes different shells can use the same startup files. For example, sh and bash can both execute $HOME/.profile, and csh and tcsh can both execute $HOME/.login and $HOME/.cshrc (though shell-specific startup files like .bashrc, .bash_profile, and .tcshrc can override those). If your default shell is /bin/csh and you want to use /bin/tcsh, updating your .login to invoke /bin/tcsh -l could create an infinite loop. zsh doesn't happen to execute bash-specific startup files, so that's not an issue for you.

Most shells set variables that identify which shell you're running ($BASH_VERSION, $tcsh, $ZSH_VERSION). If you're going to write startup code to invoke your preferred shell, it's not a bad idea to enclose it in an if so it's executed only if you're not already running that shell. Using the code from konsolebox's answer:

if [ "${ZSH_VERSION:-unset}" = "unset" ] ; then
    export SHELL=/bin/zsh
    exec /bin/zsh -l
fi

(The added complication of checking "${ZSH_VERSION:-unset}" rather than just "$ZSH_VERSION" allows for the possibility that you've done set -o unset, an option that causes a reference to an undefined variable to be an error.)