🐟

zsh からおおまかに設定を引き継いでターミナルで fish を使う

2021/08/01に公開

fish shell が便利らしいと聞いたし使ってみたいけど、

  • fish をターミナルのデフォルトのシェルで使うとWMが立ち上がらないとかの不具合が出て困ったり
    • Manjaro(GNOME) とかで起きます
  • .zshrc に書いた環境変数やコマンド群を設定し直すのが面倒だったり

してちょっと手が伸びない……

という人に向けて、 zsh ( .zshrc ) をログインシェル・各種設定に使ったまま、 fish を使う設定を書いておきます。

動作環境

  • MacOS
  • Linux
    • 特に Manjaro

zsh をデフォルトシェルにしていて、fishに移行したい人ならたいてい当てはまると思います。。。

こうする

.zshrc末尾に このように書きます。

.zshrc
if [[ -o interactive ]]; then
    exec fish
fi

なぜこうなるのか

設定・環境変数を引き継ぐため

exec [COMMAND] とすることで、環境変数を引き継いだ状態で指定したコマンドを実行することができます。

これを .zshrc 末尾で行うことで .zshrc に書いてある既存の設定・コマンドをすべて実行し、可能な限り多くの設定を保持したまま fish を起動できるというわけです。

POSIX sh 依存の状況を避けて fish を起動するため

一部のWMやディストロでは POSIX 互換なシェル(ないし bash)で動くことが前提のシェルスクリプトが使われていることがあります。 fish は POSIX 非互換なシェルなので、そういったシステムに対してデフォルトシェルを fish に設定するとエラーが発生してしまうことがあります。[1]

これを避けるには、 POSIX sh に依存するものが実行されないであろうタイミングでのみ fish を起動する必要があります。それいつ?という感じですが、たいていの場合は「シェルがインタラクティブシェルとして呼び出されているとき(≒ターミナルエミュレータから呼び出されているとき)」です。

zsh では -o interactive で自身がインタラクティブシェルか否かを判定できます。これを使って、POSIX sh 依存のものが動かないタイミングで fish を起動するようにしています。

bash ではこうする

デフォルトシェルが bash のディストロ(ほとんどですね)では、以下の記事を読むとよいです。

実はあまり意識しなくてもよくて、 .bashrcexec fish と書くだけでよかったりするのですが……。
ちゃんとやる場合の戦略は本記事と同様、インタラクティブシェルかどうかを判定する流れになるようです。

こんなときは

ターミナル・WM が起動しなくなった!

fish を使うようにしたことでターミナルを開く・WMを起動するのに失敗することがあります。
以下のような方法で復帰ができるかもしれません。

  • ターミナルの設定を操作し、起動時のコマンドを sh や他のシェルを実行し、設定変更を試みる
    • zsh がデフォルトシェルの人は bash がまだ使える可能性が高いです
  • Ctrl + Alt + F2 (, F3, F4...) で他の tty へ切り替えて、設定変更を試みる
  • 適当なLinuxのブートディスクを用意して、それを使って設定変更を試みる
    • GUIがいい人は Ubuntu のインストールディスクが楽です
    • CLIでいい人は ArchLinux のインストールディスクで arch-chroot するのが楽です

おわりに

MacOSだと単に exec fish で問題なかったのですが、
Manjaroに同じ .zshrc を食わせたらログインできなくなり、
悲しみを感じました。

zsh はログインシェルであろうと非ログインシェルであろうと .zshrc を読もうとするのでこういうハマりがちょくちょく発生します。

References

脚注
  1. なお、MacOSは雑にデフォルトシェルをfishにしても動いたりします ↩︎

GitHubで編集を提案

Discussion