問題:フリーズするターミナル
設定作業に没頭している最中、5分間のコーヒー休憩を取って戻ってくると、ターミナルが完全に反応しなくなっていることがあります。数秒間、必死にキーを叩いた後、あの忌まわしいメッセージが表示されます。
packet_write_wait: Connection to 192.168.1.100 port 22: Broken pipe
これは単なる小さな悩みではありません。ワークフローを中断させ、実行中のプロセスを終了させ、再認証して作業ディレクトリに戻る手間を強いることになります。
なぜ「Pipe」は壊れるのか?
Broken pipe エラーは、SSHクライアントが、相手側(または経路上のデバイス)がすでに閉じてしまった接続を通じてデータを送信しようとしたときに発生します。これには通常、3つの原因があります。
- 強引なファイアウォールルール: 多くの企業用ファイアウォールや家庭用NATルーターは、リソースを節約するために、300秒(5分)経過した「アイドル状態」の接続をメモリから自動的に削除します。
- サーバー側のタイムアウト: セキュリティを維持するため、リモートサーバー側で、一定時間入力がないユーザーをキックするように設定されている場合があります。
- ネットワークの変動: Wi-Fiが瞬断したり、VPNがサーバーを切り替えたりすると、ローカルIPアドレスが変更され、既存のTCPソケットが即座に無効になることがあります。
修正方法
最も信頼できる修正方法は、「KeepAlive」パケットを有効にすることです。これらはSSHトンネルを通じて送信される、ごく小さな暗号化されたハートビート信号です。これにより、ファイアウォールが接続をアイドル状態と見なさない程度に通信を維持します。
方法1:クライアント側の修正(ほとんどのユーザーに推奨)
これが推奨される方法です。リモートマシンの管理者権限を必要とせず、接続するすべてのサーバーに対して問題を解決できます。
- ローカルのSSH設定ファイルを開きます(存在しない場合は作成します):
nano ~/.ssh/config
- ファイルの先頭に以下の行を追加します:
Host * ServerAliveInterval 60 ServerAliveCountMax 3
- 保存して終了します(Ctrl+O、Enter、Ctrl+X)。
**仕組み:** これにより、コンピュータは60秒ごとに「nullパケット」を送信するようになります。サーバーがこれに3回連続で応答しなかった場合(合計180秒後)、クライアントは正常にセッションを終了します。これにより、切断されたネットワークの応答を待ってターミナルが15分間もハングするのを防ぐことができます。
### 方法2:サーバー側の修正(管理者向け)
複数のサーバーを管理しており、チームのメンバーがキックされないようにしたい場合は、ホスト側のSSHデーモン設定を変更します。
- グローバルなSSH設定を編集します:
```
sudo nano /etc/ssh/sshd_config
- 以下のディレクティブを探すか追加します:
ClientAliveInterval 60
ClientAliveCountMax 3
- サービスを再起動して新しいルールを適用します:
sudo systemctl restart ssh
### 方法3:クイックなコマンドライン・ハック
共有のコンピュータや借りたターミナルを使用していて、設定ファイルを編集できない場合は、接続コマンドに直接設定を渡します:
ssh -o ServerAliveInterval=60 user@192.168.1.100
## 結果のテスト
確認は簡単です。サーバーに接続し、そのまま放置してみてください。15分間何もしなくても、`ls` や `htop` が実行できれば、ハートビートが機能しています。中間ルーターのNATテーブルが、60秒ごとのパケットによって最新の状態に保たれています。
## 不安定な接続のためのプロのヒント
**TCPKeepAliveの罠を避ける:** チュートリアルによっては `TCPKeepAlive yes` という設定を見かけるかもしれません。似ているように聞こえますが、この設定はSSHレイヤーではなくTCPレイヤーで動作します。多くのスマートファイアウォールはこれらのパケットを無視したり偽装したりするため、`ServerAliveInterval` の方がはるかに堅牢な選択肢です。
**Mosh をモバイルワークに使用する:** 電車やカフェ、あるいは携帯電話のホットスポット経由で作業することが多い場合は、**Mosh (Mobile Shell)** を試してみてください。SSHとは異なり、MoshはUDPを使用し、ローミングをサポートしています。ラップトップを閉じたり、Wi-Fiネットワークを切り替えたりしても、再び開けばセッションを中断したところから再開できます。
**常に Tmux を使用する:** 長時間実行するスクリプトの場合は、常に `tmux` や `screen` のセッションを開始してください。たとえ「pipe」が壊れても、プロセスはサーバー上で実行され続けます。再接続して `tmux attach` を実行するだけで、作業を中断した場所から再開できます。

