SSH接続時に tmux を自動起動させる

create
2021年08月09日
update
2021年08月09日

🏄やりたいこと

SSH接続時にはいつも tmux [1][2]を起動させるので、どうせなら自動起動させたい。

Table 1. 環境
Server Client

OS

Debian10
(RaspberryPi OS Lite)

Windows10 Pro

OpenSSH

8.4p1

7.7p1

tmux

2.8

 — 

🔭 tmux をSSH接続後に自動起動させる方法について

クライアント側からやる方法と、サーバー側でやる方法の2通り。
クライアント側を推奨

サーバー側での設定が非推奨の理由
うっかり設定を間違えてSSH接続が不可能になり死んだ、という悲劇が起こり得るため。
あと、SSH接続を使うツール(Ansible とか)で不具合が出たときが面倒(クライアント側なら別の ssh_config を参照させればいいだけなので修正が簡単)。

🌟クライアント側でやる場合(推奨)

ssh_config の設定に追記するだけで達成できる。
以下のように、SSH接続後にリモート側で実行するコマンドを指定する RemoteCommand プロパティを設定すればいい。

Example 1. クライアント側
~/.ssh/config の例
 Host raspi
   HostName      192.168.1.10
   User          pi
   Port          2222
   IdentityFile  %d/.ssh/id_ed25519
+  RequestTTY    yes    (1)
+  RemoteCommand tmux new-session -A -s %r   (2)
1 ssh--tty オプションと同じく、常に疑似 TTY を要求する。
この設定がないと open terminal failed: not a terminal エラーが発生する。
2 リモートログイン後に実行するコマンド。
ここでは tmux を利用するコマンドを指定。
Table 2. 実行する tmux コマンドについて
Command Desc

new-session

新規セッションを作成。

-A

既存のセッションがあれば接続し、新規作成はしない。
attach-session と同様のふるまいにする)

-s

セッション名を指定。

%r

リモートユーザー名を表す。
ssh_config にて利用できる定数(参考)。

あとは通常通りにSSH接続すれば、tmux が起動された状態になる。
またデタッチするとSSH切断される。

😕サーバー側でやる場合

~/.profile ファイル[3]に以下のようなスクリプト文を追記すればいい。

Example 2. サーバー側

tmux のセッション内ではなく、SSH接続中であり、対話的なシェル(インタラクティブモード)であれば tmux を起動する。

サーバー側で tmux 自動起動の設定
tee -a ~/.profile <<'EOF'

# Auto start tmux when SSH connecting
if [ -z "$TMUX" ] && [ -n "$SSH_TTY" ] && [[ $- =~ i ]]; then   (1) (2) (3)
    tmux new-session -A -s "$USER"
fi

EOF
1 [ -z "$TMUX" ]: tmux のセッション内でなければ真。
2 [ -n "$SSH_TTY" ]: SSH接続中であれば真。
3 [[ $- =~ i ]]: bash が対話的なシェルであれば真。
[[ $- =~ i ]] について補足

PS1 is set and $- includes i if bash is interactive, allowing a shell script or a startup file to test this state.

とうことらしい。
よって、$-i 文字が含まれているか調べる [[ $- =~ i ]] が真ならば対話的なシェルだと判別できる。

authorized_key ファイルにおいて、command オプションを使うことでも実装できるらしい。

自動化できて快適!🤗


1. 端末多重化ソフトと呼ばれる。セッションという単位で複数のターミナルを単一ウィンドウ管理できる。
2. SSH接続が切断されても作業中のセッションはバックグラウンドとして継続され、再接続できるのがえらい。
3. もしくは ~/.bash_profile または ~/.bash_login の3つのうちいずれか1つ。