2020-03-16

MSYS2のtmuxで分割しまくったらクラッシュした件

Windows上でLinuxと同様のコマンドを使用できるMSYS2 が欠かせない。これ無しではWindowsの作業効率が7割低下すると思う。WSL2 が出たら乗り換えるかもしれないが…。

MSYS2で使えるLinuxプログラムの一つにtmuxがあり、シェルスクリプトと組み合わせることで、ターミナルを分割して複数コマンドを同時に起動させることができる。自宅の複数PCの更新作業(pacman)を同時にやったり、sshトンネルを複数立ち上げる作業を自動化したりと役立っている。が、今回それがクラッシュする問題が起きた。

以下は修正後のスクリプト。(一部内容を伏せてます)

#!/bin/bash

# シェルの起動を待つ。
# MSYS2はシェルの起動が遅いため、少し待って上げる必要がある。
# 私の環境ではPS1のドル記号の直前で改行しているので、それを探し出す。
wait_shell_prompt() {
  local i
  for i in {1..200}; do
    if tmux capture-pane -pJ -t "$1" | grep -qs '^\$'; then
      return 0
    fi
    sleep 0.5
  done
  # timeout after 10sec
  return 1
}

set -e

tmux new-window
# "-v"を付けない場合、3度目の分割でなぜかクラッシュする
tmux split-window -v
tmux split-window -v
tmux split-window -v
tmux select-layout even-vertical
wait_shell_prompt 0
wait_shell_prompt 1
wait_shell_prompt 2
wait_shell_prompt 3
tmux set synchronize-panes on
tmux send-keys 'HISTFILE='
tmux send-keys Enter
tmux set synchronize-panes off
# パスフレーズ無しのSSH鍵で接続できることが前提
tmux send-keys -t 0 "ssh -vNL 2080:192.168.11.193:2080 -o ServerAliveInterval=5 $host"
tmux send-keys -t 1 "ssh -vNL 4000:localhost:4000 -o ServerAliveInterval=5 $host"
tmux send-keys -t 2 "ssh -vNR 4444:localhost:4444 -o ServerAliveInterval=5 $host"
tmux send-keys -t 3 'selenium-server-standalone'
tmux set synchronize-panes on
tmux send-keys Enter
tmux rename-window tunnels

各コマンドの意味は各自man tmuxを参照していただくとして(英語から大体読み取れると思うけど)、問題となった部分はtmux split-window -vの部分。

-vはターミナルを縦に分割する、の意で、付けなくてもデフォルトで縦分割される。そのため、付けないでいたのだが、3つ目の分割を実行した場合にクラッシュした。スクリプトではなく、コマンドを手で打ってもそうなる。ならない場合もある。tmux new-windowの直後に行うと発生する傾向がある。

分割を繰り返してペインが小さくなると分割方向のアルゴリズムがおかしくなってクラッシュするとかいうことか?イマイチしっくり来ないが…。

ちなみに当記事執筆中に何度か試したら発生しなかった。再現できなかったので正確なエラーメッセージはわからないけどserver unexpectedly exitedみたいな文字列だったと思う。

お問い合わせはこちらまで: @matil019 リプにブログのリンクを含めていただけるとスムーズに会話できます。
記事一覧