Changing default shell from zsh to bash on MacOS (Catalina and beyond) [closed]
Asked Answered
M

1

6

I felt comfortable using bash shell on MacOS. But Catalina replaced it with zsh.

Why? Can I switch it back?

If so, how?

Does it make sense to do so? Any gotchas?

Maze answered 6/9, 2023 at 13:59 Comment(2)
Stack Overflow is specific to questions about writing code. Super User is Stack Exchange's general user-focused-support site, but there's also Ask Different and Unix & Linux, either of which could be defensible as well.Outdoors
It's not that Tim Cook will come in person to punish you if you don't follow his recommendations. For your login shell, you can (if you want) use any shell you feel comfortable, but don't forget that the bash which comes free with MacOS, is pretty old and you may want to install a more recent one. What exactly are you using your default login shell for? In practice, most of the time you will start the shell from Terminal.app (or something similar), and in this case, you can explicitly set in the preference, which shell to use.Exceedingly
M
13

TLDR

  • Install desired bash: brew install bash

  • Confirm the path: /opt/homebrew/bin/bash --version (If it's different, adapt the below accordingly).

  • sudo nano /etc/shells and insert /opt/homebrew/bin/bash at the top of the list. This is so the next instruction will succeed.

  • Change default login shell: chsh -s /opt/homebrew/bin/bash

  • Close and reopen your terminal program, and echo $SHELL to confirm the running shell is indeed /opt/homebrew/bin/bash

  • Now tweak so a terminal session can see homebrew locations: nano ~/.bash_profile (it will create it if it's empty) and add the line:

eval "$(/opt/homebrew/bin/brew shellenv)"
  • Test it worked: close and reopen your terminal program, then:
> echo $SHELL
/opt/homebrew/bin/bash  # location of the running shell program

> echo $BASH_VERSION  # version of the running shell program
5.2.15(1)-release

> which bash  # check our $PATH contains homebrew locations
/opt/homebrew/bin/bash

> bash --version  # check this is consistent with above
GNU bash, version 5.2.15(1)-release (aarch64-apple-darwin22.1.0)
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Deep dive

MacOS ships with the latest BASH that uses LGPL v2 license:

> which bash
/bin/bash

> /bin/bash --version
GNU bash, version 3.2.57(1)-release (arm64-apple-darwin23)
Copyright (C) 2007 Free Software Foundation, Inc.

You can install latest bash (e.g. with homebrew)

> brew install bash
:

> brew info bash
==> bash: stable 5.2.15 (bottled), HEAD
:

What happened here? AFAIK after 3.2.x, the bash license changed from LGPL v2 to v3. Apple refused to morph into compliance LGPL v3, instead fixing the bash version shipping with MacOS to 3.2.x. Eventually it became awkward, and (2019/Catalina) they switched to zsh (MIT license).

Now we need to use chsh to change the default login shell to the new bash, but first we'll need to locate the executable.

NOTE: Annoyingly,

> brew --prefix bash
/opt/homebrew/opt/bash

... is a wild goose chase as you'd rabbithole into how homebrew stores packages (.../Cellar), symlinks to the latest version (.../opt) and exposes relevant binaries (.../bin). So let's not go there for now.

Here are the PATHs homebrew requires.

> brew shellenv
export HOMEBREW_PREFIX="/opt/homebrew";
export HOMEBREW_CELLAR="/opt/homebrew/Cellar";
export HOMEBREW_REPOSITORY="/opt/homebrew";
export PATH="/opt/homebrew/bin:/opt/homebrew/sbin${PATH+:$PATH}";
export MANPATH="/opt/homebrew/share/man${MANPATH+:$MANPATH}:";
export INFOPATH="/opt/homebrew/share/info:${INFOPATH:-}";

Let's add these paths into the current shell session and locate the executable:

> which bash
/bin/bash

> bash --version
GNU bash, version 3.2.57(1)-release (arm64-apple-darwin23)
Copyright (C) 2007 Free Software Foundation, Inc.

> eval "$(brew shellenv)"

> which bash
/opt/homebrew/bin/bash

> bash --version
GNU bash, version 5.2.15(1)-release (aarch64-apple-darwin22.1.0)
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Now we'll use chsh to change the default login shell to /opt/homebrew/bin/bash.

chsh will only accept a shell listed in /etc/shells, so edit that file and insert the line (e.g. with sudo nano /etc/shells.

Now you should see:

> cat /etc/shells
# List of acceptable shells for chpass(1).
# Ftpd will not allow users to connect who are not using
# one of these shells.

/opt/homebrew/bin/bash
/bin/bash
/bin/csh
/bin/dash
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh

Now chsh will work:

chsh -s /opt/homebrew/bin/bash

Close and reopen your terminal program. Now:

> echo $SHELL
/opt/homebrew/bin/bash

> echo $BASH_VERSION
5.2.15(1)-release

... to confirm it worked.

However there's one remaining gotcha:

which bash
/bin/bash

This is because those homebrew PATHs we listed earlier aren't added to our shell session anywhere.

To fix, edit (creating if necessary) ~/.bash_profile and add the line:

eval "$(/opt/homebrew/bin/brew shellenv)"

Now restart your terminal program and both echo $SHELL and which bash should now be in alignment. More importantly, your shell now has visibility over homebrew locations.

Maze answered 6/9, 2023 at 13:59 Comment(5)
In How to Answer, note the section Answer Well-Asked Questions, and therein the link to stackoverflow.com/help/on-topic.Outdoors
(BTW, personally, I strongly advise using Nix in place of Homebrew; in the Homebrew world you end up with a directly user-writable location that multiple users can access, making it easy for malware to persist itself; in a multi-user Nix installation, by contrast, only the Nix daemon can write to /nix/store locations, and a user only gets a hash associated with a store location when they deliberately attempt to reference the build instructions used to compile a piece of software; so if one user installs a poisoned copy of bash with Nix, it's only poisoned for them)Outdoors
One note about echo $SHELL -- it's not the running shell, it's the user's login shell: gnu.org/software/bash/manual/bash.html#index-SHELLBrochure
(another reference re: SHELL, perhaps more canonical: pubs.opengroup.org/onlinepubs/9699919799/basedefs/…)Outdoors
A note about which bash -- Why not use "which"? What to use then?Brochure

© 2022 - 2024 — McMap. All rights reserved.