46

I want to change my shell from bash to zsh.

I have tried running the following while logged in as user zol:

$ chsh -s /bin/zsh
$ sudo chsh -s /bin/zsh zol
$ su -c 'chsh -s /bin/zsh zol'
# The above all results with:
$ password:
$ chsh: Shell not changed.

# zsh exists in /etc/shells.. 
chsh -l
/bin/sh
/bin/bash
/sbin/nologin
/bin/zsh

What could be wrong? How can I fix it?

5
  • Did you try running 'chsh' without any arguments as zol? Commented Jun 2, 2012 at 14:48
  • Are you using something like ldap/nis etc.? Commented Jun 2, 2012 at 14:53
  • Much more importantly: Why doesnt it give you more info? That message might be fine for a seasoned sysop but for most people it's downright rude. Im facing the same problem 5 years on, and people wonder why linux has spent the past 20 years not on the desktop. Commented Sep 4, 2017 at 12:26
  • You expected your shell to change instantly? You change your login shell with chsh, which means you will have to log in again. Commented Nov 6, 2019 at 17:02
  • I was working with VSCode and seems it keeps a separate default shell (independent of the system shell)... Commented Feb 17, 2023 at 21:07

8 Answers 8

37

User account modifications will not be saved if you have opened /etc/passwd (vim /etc/passwd) when you try to change the info.

Alternative: try with usermod (as zol):

$ usermod -s /bin/zsh 

or

$ sudo usermod -s /bin/zsh zol

If this doesn't work either, edit /etc/passwd by hand.

sudo vipw
# set zol's shell to /bin/zsh
:wq
6
  • 10
    please use vipw instead of vim as they set the appropriate file locks. Commented Jun 2, 2012 at 15:06
  • "User account modifications will not be saved if you have opened /etc/passwd" — but why? Commented Feb 3, 2015 at 19:44
  • It doesn't work too. When I restart Linux virtual machine (centos7), it's OK now! Commented Jul 11, 2016 at 10:56
  • 1
    @fromnaboo Can you please explain why you make this claim in your first sentence, as @ Thanatos already asked ? You have not provided any explanation about this, and this seems to spawn out of nowhere, as is. Commented Dec 2, 2020 at 10:07
  • 1
    @Atralb because vi/vim overwrites the original with your new version when you save the file. That's partly why you should always use vipw instead of vi[m], because it locks the file against other changes as well as checking the syntax of the file before updating it Commented Jun 20, 2024 at 13:08
19

Just ran into this. No matter what I did logging in and back out would not change my shell yet it was listed in /etc/shells and in /etc/passwd.

finally it dawned on me: Maybe I am logged in with another session?

So I did

# who

and it validated I did have indeed other open sessions from other machines:

dom  pts/0        Nov 6 13:53 (10.1.6.121)
dom  pts/1        Nov 5 12:30 (10.1.6.165)
dom  pts/2        Nov 4 12:33 (10.1.6.197)

I then did:

pkill -KILL -u dom

I was immediately logged out and after logging back in: Voila! Shell was changed

1
  • 2
    It works, why "logged in with another session" create a problem? Commented Sep 8, 2022 at 12:39
12

If you see chsh: Shell not changed., it could mean that the shell was already changed.

Check which shell is listed:

cat /etc/passwd | grep `cd; pwd`

If it's correct, log out and back in to have the change take effect.

1
  • 1
    Thanks! This was my rookie mistake. I had to log out and log in again for the change to take place. Commented Nov 21, 2022 at 21:02
3

When to run "chsh -l" if you to see:

/usr/bin/zsh
/bin/zsh

Then use:

chsh -s /usr/bin/zsh

Warning: The commands was run on Fedora 25, In ubuntun the option "-l" from is out.

4
  • 1
    -l is an invalid option for me. I'm on Ubuntu 16.04 Commented Jul 27, 2017 at 10:39
  • Sorry, I don't give information about the distro where the commands work. In my case I tested on Fedora 25. I try on ubuntu and I verify the option "-l" is out. Commented Jul 27, 2017 at 13:18
  • Regardless, chsh -s worked perfectly. Thanks. Commented Jul 27, 2017 at 13:33
  • The option is valid on Manjaro but it still refuses to change the shell. Commented Sep 4, 2017 at 12:28
-1

Change it from /etc/passwd

I had some problems with zsh (that is default in manjaro) and I used it for get back to bash.

[infinito@manjaro ~]$ grep infinito /etc/passwd
infinito:x:1000:1000:Sergio N:/home/infinito:/bin/bash      <---here
1
  • 1
    Ordinary users can't edit /etc/passwd. Commented Dec 11 at 0:32
-1

if im right

sudo chsh -s /bin/zsh zol

is the correct command

the above command actually changes the shell but the problem with this is that you are logged in as that user here username "zol" so try logging out and comming back, this works

1
  • Is there a reason you need to be root to change your shell? Commented Dec 11 at 9:25
-1

For some it may be a "big gun to kill an ant", but I did it in my free time to practice some things in shell.

Below is my "elegant" solution to change the default shell interactively and with some contingencies to ensure that it is changed according to the user's choice:

#!/usr/bin/env bash

clear_screen() {
  sleep 1
  printf "\033[2J\033[H"
}
# Clears the terminal screen after a short pause.

# Function to check if the shell is available
# Arguments:
#   $1 - The shell to check
# Returns:
#   0 if the shell is available, 1 otherwise
check_shell_available() {
    local shell=$1
    echo "$_AVAILABLE_SHELLS" | grep -q "$shell"
}
# Checks if the specified shell is available in the list of known shells.

# Function to check if the shell is safe
# Arguments:
#   $1 - The shell to check
# Returns:
#   0 if the shell is safe, 1 otherwise
check_shell_safe() {
    local shell=$1
    # List of allowed shells that i know are safe (sweet yourself with your own list)
    local allowed_shells=(
      "/bin/sh" "/usr/bin/sh"
      "/bin/bash" "/usr/bin/bash"
      "/bin/rbash" "/usr/bin/rbash"
      "/bin/dash" "/usr/bin/dash"
      "/bin/zsh" "/usr/bin/zsh"
      "/usr/bin/fish"
      "/usr/bin/screen"
      "/usr/bin/tcsh"
      "/usr/bin/ksh"
      "/usr/bin/mksh"
      "/usr/bin/lksh"
      "/usr/bin/oksh"
      "/usr/bin/posh"
      "/usr/bin/yash"
      "/usr/bin/elvish"
      "/usr/bin/xonsh"
    )
    local forbidden_shells=("/bin/false" "/usr/sbin/nologin")
    [[ " ${allowed_shells[*]} " == *" $shell "* ]] && [[ -x $shell ]] && [[ $shell == /* ]] && [[ ! " ${forbidden_shells[*]} " == *" $shell "* ]]
}
# Checks if the specified shell is allowed and safe to use.

# Function to change the user's shell
# Arguments:
#   $1 - The shell to change to
change_user_shell() {
    local shell=$1
    sudo usermod --shell "$shell" "$(id -un)"
}
# Changes the user's shell to the specified shell using the usermod command.

# Function to verify if the shell was changed
# Arguments:
#   $1 - The shell to verify
# Returns:
#   0 if the shell was changed, 1 otherwise
verify_shell_change() {
    local shell=$1
    local current_shell
    current_shell=$(grep "^$(id -un):" "$_PASSWD_FILE" | cut -d: -f7)
    [ "$current_shell" == "$shell" ]
}
# Verifies if the user's shell was successfully changed.

printf "Starting script...\n"

# Check if the user is in the sudo group
if ! groups | grep -q '\bsudo\b'; then
    printf "The user is not in the sudo group.\n"
    exit 1
fi

# Check if the dialog command is available
if ! command -v dialog &> /dev/null; then
    # Ask the user if they want to install dialog
    printf "The dialog command is not available. Do you want to install dialog? (y/n) "
    read -r response
    if [[ ! "$response" =~ ^[Yy]$ ]]; then
      printf "Dialog installation canceled.\nPackage required to continue.\n"
      exit 0
    fi
    if ! sudo apt-get install -y dialog; then
        echo "Could not install dialog."
        exit 1
    fi
    clear_screen
fi

# Update the list of available shells, if possible
command -v update-shells &> /dev/null && sudo update-shells
# Updates the list of known shells, if the update-shells command is available.

# Get the list of available shells
_AVAILABLE_SHELLS=$(grep -v '^#' "/etc/shells" | tr '\n' ' ')

# Display the list of available shells for the user to choose
# shellcheck disable=SC2086
_SHELL=$(dialog --menu "Choose the shell you want to use:" 15 50 10 $_AVAILABLE_SHELLS 3>&1 1>&2 2>&3)
# Displays a dialog menu for the user to select the desired shell.

# Check if the shell is available
if ! check_shell_available "$_SHELL"; then
    dialog --msgbox "The shell you entered is not available." 10 50
    exit 1
fi

# Check if the shell is safe
if ! check_shell_safe "$_SHELL"; then
    dialog --msgbox "The shell you entered is not safe." 10 50
    exit 1
fi

# Ask the user if they want to perform the operation
dialog --yesno "Do you want to change the shell to $_SHELL?" 10 50
response=$?
if [ $response -ne 0 ]; then
    exit 0
fi

_PASSWD_FILE="/etc/passwd"

# Try to change the shell using chsh
chsh -s "$_SHELL"
# Attempts to change the user's shell using the chsh command.

# Verify if the shell was changed
if ! verify_shell_change "$_SHELL"; then
    # Try to change the shell using usermod
    change_user_shell "$_SHELL"
    # Attempts to change the user's shell using the usermod command.

    # Verify if the shell was changed
    if ! verify_shell_change "$_SHELL"; then
        # Try to change the shell directly in the passwd file
        _CURRENT_SHELL=$(grep "^$(id -un):" "$_PASSWD_FILE" | cut -d: -f7)
        _OLD_LINE=$(grep "$(id -un):x:$(id -u):$(id -g)" "$_PASSWD_FILE" | grep "$(which "$_CURRENT_SHELL")")
        _NEW_LINE="${_OLD_LINE//$(which "$_CURRENT_SHELL")/$(which "$_SHELL")}"
        sudo sed -i "s|$_OLD_LINE|$_NEW_LINE|" "$_PASSWD_FILE"
        # Directly modifies the /etc/passwd file to change the user's shell.

        # Verify if the shell was changed
        if ! verify_shell_change "$_SHELL"; then
            dialog --msgbox "Could not change the shell." 10 50
            exit 1
        fi
    fi
fi

dialog --msgbox "Shell successfully changed to $_SHELL." 10 50

dialog --msgbox "Restart the session to apply the changes." 10 50

clear_screen

exit 0

Feel free to change the trusted list and the methods of changing them or the order in which you try them.

If you have any questions, I'm here to answer them, just ask. (I'm also willing to make edits, if necessary)

Hope you like it!

EDIT: I added more explanatory comments about each method.

-2

I got this error when installing zsh and ohmyzsh. I rebooted system to clear ssh first shell session and it worked. SO I change it and got this same error msg. Then I reboot. Now it loads zsh instead bash.

1
  • 1
    This does not really answer the question. If you have a different question, you can ask it by clicking Ask Question. To get notified when this question gets new answers, you can follow this question. Once you have enough reputation, you can also add a bounty to draw more attention to this question. - From Review Commented Dec 10 at 23:13

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.