Skip to content
Published on

SSH Escape Sequences 実践ガイド: 固まったセッション終了、ライブトンネル追加、リモート運用復旧

Authors
  • Name
    Twitter

なぜ今この話題を見直すべきか

今回の自動化ラン日付である 2026年3月16日 時点で、GeekNews のトップでは SSH の escape menu が再び話題になっていた。AI ツールやクラウド運用が当たり前になっても、bastion 接続、障害対応、緊急デバッグ、臨時トンネルの基本手段は依然として SSH であり、そこで使える組み込み制御機能を見落としがちだからだ。

本記事は噂や断片的な tips ではなく、OpenSSH 公式の ssh(1)ssh_config(5) を基準に整理している。ローカル検証に使用したクライアントは OpenSSH_10.2p1 だった。プラットフォームやバージョンで既定値は変わり得るため、最終確認は必ず man sshman ssh_config で行うべきだ。

1. escape sequence が動作する前提条件

SSH escape sequence はどのセッションでも使えるわけではない。公式マニュアルから実務上重要な条件を抜き出すと次の通りだ。

条件意味実務メモ
PTY が必要ssh(1) は pseudo-terminal が割り当てられたセッションで escape sequence をサポートするssh -T や非対話コマンド実行では動作しない場合がある
行頭である必要があるescape 文字は 改行直後の行頭 でのみ特別扱いされるシェル入力の途中で ~. を打っても何も起きない
既定の escape 文字は ~ビルトインの既定値-eEscapeChar で変更可能
EscapeChar none も有効escape 処理を完全に無効化できるバイナリ透過性やコンソール用途で有効

実際の手順は単純だ。

1. Enter を一度押す
2. 次の行頭で ~? または ~. を入力する

2. 覚えておく価値がある escape sequence

ssh(1) が文書化している主要な escape sequence を、運用観点で整理すると次のようになる。

シーケンス機能使いどころ注意点
~?利用可能な escape 一覧表示メニューを忘れたとき行頭で入力する
~.即時切断固まったセッションの切り離し強力なので誤入力注意
~~文字として ~ を送るREPL、heredoc、設定編集行頭で必要になることが多い
~^ZSSH をバックグラウンドへ一時的にローカルシェルへ戻りたいときjob control があると使いやすい
~&forward/X11 の終了待ちをしながらバックグラウンド化トンネルは残して端末だけ空けたいとき終了タイミングを理解して使う
~#現在の forward 一覧表示どの -L/-R/-D が有効か確認するときインシデント時に特に有効
~R再鍵交換(rekey)要求長時間セッション相手が対応している必要がある
~v / ~Vstderr に出るログ詳細度を増減再接続せずにその場でデバッグstderr リダイレクト時に注意
~Bリモートへ BREAK 送信ネットワーク機器やシリアル系コンソール通常の Linux シェルでは出番が少ない
~CSSH コマンドラインを開く再接続せずに forward を追加・取消現在の ssh_config(5) では EnableEscapeCommandline に注意

3. 実際に役立つ運用パターン

3.1 固まったセッションをすぐ切る

VPN の瞬断や TCP 経路の劣化で、シェルが半分固まったまま exit すら返ってこないことがある。そんなときの最短脱出手段はこれだ。

Enter
~.

これが有効な理由:

  • ローカル SSH クライアント自身に接続整理を指示できる
  • 端末プロセス全体を kill するより影響範囲が小さい
  • 複数セッションを開いていても壊れたものだけ処理できる

単に一時退避したいだけなら ~^Z の方が適している。

3.2 再接続せずに port forwarding を足す

運用では次のような状況がよくある。

  • すでに bastion に入って障害を見ている
  • そこへ一時的な DB トンネルを 1 本追加したい
  • あるいはローカル SOCKS proxy を足して UI を確認したい
  • 古い forward だけを消してシェルは維持したい

~C コマンドラインはまさにこのためにある。公式マニュアルは、-L, -R, -D の追加と既存 forward の取消をサポートすると明記している。

Enter
~C
ssh> -L 15432:db.internal:5432
ssh> -D 1080
ssh> -KL15432
ssh> -KD1080

意味は以下の通りだ。

  • -L 15432:db.internal:5432: ローカル 15432 をリモート DB 5432 に接続
  • -D 1080: ローカル SOCKS proxy を追加
  • -KL15432: ローカル forward 15432 を取消
  • -KD1080: dynamic forward 1080 を取消

ここで重要なのは、現在の OpenSSH ssh_config(5)EnableEscapeCommandline の既定値を disabled と文書化していることだ。つまり、~C が動かない環境は珍しいのではなく、設定差分の可能性がある。

3.3 ~C を安定して使うための host profile

挙動を予測可能にしたいなら、host ごとに明示設定した方がよい。

Host bastion-prod
  HostName bastion.example.com
  User ops
  ServerAliveInterval 15
  ServerAliveCountMax 3
  TCPKeepAlive yes
  ControlMaster auto
  ControlPath ~/.ssh/cm-%C
  ControlPersist 10m
  ExitOnForwardFailure yes
  EnableEscapeCommandline yes

運用上の意味は次の通り。

  • 約 45 秒応答がなければ切断
  • control socket で接続を再利用
  • forward 失敗を黙殺しない
  • 対応クライアントで ~C を明示的に有効化

もし ~C をチーム標準にできないなら、multiplexing control socket を使う運用に寄せるのもよい。ssh(1)-O forward, -O cancel, -O exit を明示的に文書化しているので、別シェルからマスター接続を制御できる。

3.4 TCPKeepAlive だけに頼らない

keepalive 周りは見落とされやすい。ssh_config(5) は次を明確に区別している。

  • ServerAliveInterval / ServerAliveCountMax
  • TCPKeepAlive

マニュアルによると、server-alive メッセージは 暗号化チャネル上 を通り、TCP keepalive は spoofable である。長時間の bastion セッションや不安定な回線では、通常次の組み合わせが実用的だ。

Host *
  ServerAliveInterval 15
  ServerAliveCountMax 3
  TCPKeepAlive yes

これでネットワーク障害自体がなくなるわけではないが、反応しない幽霊セッションを大きく減らせる。

3.5 行頭に本物の ~ を送りたいとき

REPL や heredoc では、行頭に ~ そのものを送りたいことがある。そのときは次を使う。

Enter
~~

escape 機能自体が邪魔なら、完全に無効化する。

ssh -e none ops@host

または:

Host serial-console
  EscapeChar none

これは透過性が重要なコンソールやバイナリ系セッションに向いている。

4. 実務向けの推奨プロファイル

個人用 tweak ではなく、チームで共有しやすい最小限の運用プロファイル例を示す。

Host bastion-*
  User ops
  ControlMaster auto
  ControlPath ~/.ssh/cm-%C
  ControlPersist 10m
  ServerAliveInterval 15
  ServerAliveCountMax 3
  TCPKeepAlive yes
  ExitOnForwardFailure yes
  EnableEscapeCommandline yes

Host batch-*
  User ops
  ControlMaster auto
  ControlPath ~/.ssh/cm-%C
  ControlPersist 2m
  ServerAliveInterval 30
  ServerAliveCountMax 2

Host serial-console
  User ops
  EscapeChar none

理由は単純だ。

  • bastion は接続再利用の恩恵が大きい
  • 障害対応経路は keepalive を明示した方が事故が減る
  • 透過性が重要な経路では escape を切る方が安全である

5. よくあるつまずき

~C があるはずなのに使えない

機能が消えたというより、設定またはバージョン差分の可能性が高い。現在の ssh_config(5)EnableEscapeCommandline を別オプションとして文書化している。

~. を打ったのに切れない

多くは行頭でなかったか、PTY のないセッションだった。まず Enter を押して再試行する。

どの forward が生きているかわからない

推測せず ~# で確認する。障害対応中の推測は二次障害を作る。

もう少しログを見たい

新しい -vvv セッションを開き直す前に、~v / ~V で現在セッションの verbosity を調整できる。

6. 運用チェックリスト

  • 重要ホストに ServerAliveIntervalServerAliveCountMax を明示したか
  • bastion 用に ControlMaster, ControlPersist, ControlPath を標準化したか
  • ライブで forward を変えたいなら EnableEscapeCommandline yes を明示したか
  • 壊れたトンネルを黙殺しないよう ExitOnForwardFailure yes を有効にしたか
  • 透過性重視のコンソールでは EscapeChar none を検討したか

まとめ

SSH escape sequence は「隠し機能」というより、マニュアルを読んだ人だけが使いこなしている標準機能に近い。~., ~?, ~#, ~C と、その周辺の keepalive / multiplexing 設定を覚えるだけで、リモート運用の摩擦はかなり減る。

話題のきっかけは GeekNews だったとしても、長期的な価値はもっと地味で実用的だ。これらは OpenSSH 公式ドキュメントに裏づけられた安定した運用プリミティブであり、AI 時代の開発フローでも引き続き重要である。


Quiz (5 questions)

Q1. SSH escape sequence が解釈されるために重要な 2 条件は何か。
PTY がある対話セッションであること、そして改行直後の行頭で入力すること。

Q2. 固まったセッションを即座に切断する既定の escape sequence は何か。
~.

Q3. 現在の OpenSSH 文書で ~C コマンドライン可否に直接関係する ssh_config オプションは何か。
EnableEscapeCommandline

Q4. ServerAliveInterval が TCP keepalive 単体より信頼されやすい理由は何か。
応答確認メッセージが暗号化チャネル上を通り、spoofable ではないと文書化されているため。

Q5. 最初のセッション終了後もマスター接続をバックグラウンドに保持するオプションは何か。
ControlPersist

References