Another way to execute an interactive shell as the superuser is sudo -s, which uses $SHELL as the shell.

As the comments in the other answer mentioned, su -s /path/to/zsh doesn't work in OS X.

OS X doesn't support changing login shells in /etc/passwd either, but you can use dscl:

$ dscl . -read /Users/root UserShell
/bin/sh
$ sudo dscl . -change /Users/root UserShell /bin/sh /bin/zsh
$ dscl . -read /Users/root UserShell
/bin/zsh
$ sudo su
My-iMac# echo $0
zsh
My-iMac# exit
$ sudo dscl . -change /Users/root UserShell /bin/zsh /bin/sh
$ 

/bin/sh is not a Bourne shell anymore on most platforms. It is a POSIX-compliant version of bash in OS X and dash in Ubuntu.


From the su manpage, there are two ways you can accomplish this.


The first method is to simply use the -s or --shell flag (assuming you are using a *NIX-based OS with a version of su that supports this argument), followed by the path to the shell of your choice. If the passed shell cannot be found, su reverts to the following method, and failing that, will attempt to invoke /bin/sh.

For example, you can force su to launch zsh (assuming it exists in /bin/zsh) as:

sudo su --shell /bin/zsh

The second method is to modify the default shell specified for the root user (be careful!). This can be done by editing the file /etc/passwd and changing the shell specified for the root user. To see what shell is specified by default, you can run the following command (assuming the superuser is root):

sudo grep root /etc/passwd 

The command should output something like root:x:0:0:root:/root:/bin/bash. You can simply change the /bin/bash (or whatever is set in your system) to point to zsh instead.


A cleaner way that will also protect your system in case your custom shell is blown up is to create a .profile in root's home directory w/:

if [ -x /opt/local/bin/bash ]; then
    SHELL=/opt/local/bin/bash
    export SHELL
    exec /opt/local/bin/bash
else
    echo /opt/local/bin/bash not found using default shell of $SHELL
fi

Just change the path to the shell you want instead of bash.