December 1, 2024
この記事はひとりアドベントカレンダー(便秘解消) DAY 1の記事です。
ログイン時にtmuxを自動で起動したい場合、起動スクリプトは .zprofile
or .zlogin
に書くのがよさそう
ロケールを日本語に設定したLinuxのログインシェルでtmuxを起動したとき、日本語が表示されなかった。
具体的には、ASCIIの範囲の文字は表示されるが、それ以外はすべて _
として表示される。
また、一度tmuxを終了させてzshに抜けたとき、およびあらためてtmux起動したときは正しく日本語が表示されるようになる。
Linux worker01 6.8.12-4-pve #1 SMP PREEMPT_DYNAMIC PMX 6.8.12-4 (2024-11-06T15:04Z) x86_64 GNU/Linux
以下のansibleを実行して、日本語ロケールを生成済。
- name: '日本語ロケールの生成'
become: true
community.general.locale_gen:
name: ja_JP.UTF-8
- name: '日本語ロケールを使う'
become: true
ansible.builtin.copy:
content: 'LANG=ja_JP.UTF-8'
dest: /etc/locale.conf
tmuxの起動は、~/.zshenv
に書かれた以下のスクリプトで実行している。
# TMUX
if which tmux >/dev/null 2>&1; then
# if no session is started, start a new session
test -z ${TMUX} && tmux
# when quitting tmux, try to attach
while test -z ${TMUX}; do
tmux attach || break
done
fi
一度tmuxを終了させてzshに抜けたとき、およびあらためてtmux起動したときは正しく日本語が表示されるようになる。
この挙動から、初回のtmux起動までの時間で、設定したロケールが読まれていないのではないかと仮説を立てた。
ロケール情報は環境変数に入る。そのため、
の環境変数を比較した。
$ mkdir tmp
$ env > tmp/${現在試している状態}-env.txt
その後、環境変数を比較した。ソートをしないとまともなdiffが取れないので、環境変数名をキーにソートしている。
# 以下は初回起動とtmux再起動後の環境変数を比較している
$ zsh -c "diff -ui <(sort tmp/env-first-tmux.txt) <(sort tmp/env-re-tmux.txt)"
残念ながら、目星を付けていた LANG
には差分がなく、どの状態でも LANG=ja_JP.UTF-8
が入っていた。
tmuxのドキュメントには、
tmux will attempt to detect if the terminal it is running in supports UTF-8 by looking at the LC_ALL, LC_CTYPE and LANG environment variables. (tmuxはターミナルがUTF-8をサポートしていてLC_ALL, LC_CTYPE, LANGが設定されていたらいい感じに言語設定するよ(適当訳))
とあるので、LANGが設定されている以上詰みかと思われた。
が、ふと適当に前述したtmux起動スクリプトを ~/.zshrc
の末尾に移動してログインしなおしたところ、日本語が表示された。
neovimの :h
やmanもしっかり日本語で読めた。
もしやと思いzshの設定ファイルロード順を確認することにした。
zshのmanによると、ログイン時は以下の順で設定ファイルが読まれている
自分の環境では、ZDOTDIR
は明示的に指定していないので、~/
になる
今回、zshenv
でtmuxを起動したところ、その時点ではLANGが設定されていないような挙動を見せたため、そこを確認したい。
以下のスクリプトをZDOTDIR
の各設定ファイルに書けばログイン時の出力で必要最低限の出力が得られるはず。
echo "LANG=$(echo $LANG) in .zprofile"
結果は以下の通りで、やはりzshenvの段階でLANGが読めていなかった。
LANG= in .zshenv
LANG=ja_JP.UTF-8 in .zprofile
LANG=ja_JP.UTF-8 in .zshrc
ここまでの挙動から、/etc/zsh/zshenv
, $ZDOTDIR/.zshenv
の両方を処理したあとでtmuxを起動するのが確実そう。
以下の記事を読むと、実際zshenvには環境変数の設定だけを書いて、コマンド実行はなるべく避けたほうがよさそう、ということがわかる。
(つまりこれまでの設定はアンチパターンだったということ)
というわけで、以下のスクリプトは最終的に ~/.zlogin
で書かれることになった。
# TMUX
if which tmux >/dev/null 2>&1; then
# if no session is started, start a new session
test -z ${TMUX} && tmux
# when quitting tmux, try to attach
while test -z ${TMUX}; do
tmux attach || break
done
fi