zsh からおおまかに設定を引き継いでターミナルで fish を使う
fish shell が便利らしいと聞いたし使ってみたいけど、
-
fish
をターミナルのデフォルトのシェルで使うとWMが立ち上がらないとかの不具合が出て困ったり- Manjaro(GNOME) とかで起きます
-
.zshrc
に書いた環境変数やコマンド群を設定し直すのが面倒だったり
してちょっと手が伸びない……
という人に向けて、 zsh
( .zshrc
) をログインシェル・各種設定に使ったまま、 fish
を使う設定を書いておきます。
動作環境
- MacOS
- Linux
- 特に Manjaro
zsh をデフォルトシェルにしていて、fishに移行したい人ならたいてい当てはまると思います。。。
こうする
.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
のディストロ(ほとんどですね)では、以下の記事を読むとよいです。
実はあまり意識しなくてもよくて、 .bashrc
に exec 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
-
zsh
のexec
-
zsh
のtest -o
-
なお、MacOSは雑にデフォルトシェルをfishにしても動いたりします ↩︎
Discussion