# mosh

當網路不配合時，Mosh 能讓工作階段保持存活：從 Wi-Fi 切到行動網路、闔上上蓋、
走出訊號範圍 —— 重新連線後，工作階段依然在那裡。Tessera 還為它搭配了一項
iOS 上其他 mosh 用戶端都沒有的能力：**真正的回捲緩衝**。

Mosh 需要主機上安裝 `mosh-server`，並預設開放 UDP 連接埠 60000–61000。可在
[主機編輯器的傳輸方式設定](https://bambouville.com/docs/zh-hant/connections/#傳輸方式ssh-或-mosh)中為每台主機
個別選擇。

## 漫遊

mosh 工作階段綁定的是你的身分，而不是你的網路路徑。在 Wi-Fi ↔ 行動網路切換、
位址變更以及休眠／喚醒之間，Tessera 都保持接入 —— 工作階段就從封包中斷的地方
繼續下去。透過 VPN 或 tailnet 也是同樣的運作方式；mosh 只需要 UDP 能連到
伺服器。

## 真正的回捲緩衝

原版 mosh 沒有回捲緩衝 —— 它在設計上只同步可見的畫面，因此捲出畫面的內容根本
不會被傳送。其他 iOS mosh 用戶端都繼承了這個限制，並要你改用 tmux 的
copy-mode。

Tessera 則改為合成出這段歷史。在以 tmux 為基礎的 mosh 工作階段中，終端機走
UDP，同時由第二條 SSH 側通道與 tmux 溝通；向上捲動時，真正的歷史會透過該通道
取回並就地顯示 —— 可以用[在終端機中尋找](https://bambouville.com/docs/zh-hant/keyboard/#在終端機中尋找)搜尋、
可以選取，而且完整無缺。

![Tessera 中的一個 mosh 工作階段，向上捲動瀏覽一長串 git log，提交訊息和 diffstat 都完整算繪，下方可見 shell 提示字元。](https://bambouville.com/docs/assets/img/mosh-scrollback.png)

*一個往 git log 深處捲動的 mosh 工作階段 —— 這些歷史在原版 mosh 中早已被丟棄。*

閱讀期間它的行為如下：

- 向上捲動會顯示**凍結在原處**的歷史 —— 新的輸出不會把你拉回底部。
- 回到底部（或開始輸入）會關閉這層覆蓋，回到即時的最新畫面。
- 用力一甩會持續捲動：第一頁立即載入，其餘歷史隨後串流補上，最多到伺服器保留
  的深度為止。

## 它需要什麼

- **一種 tmux 啟動模式。** 回捲緩衝的合成適用於**自動 tmux**和**具名 tmux**
  工作階段（自動 tmux 是預設值）。以自訂指令啟動的 mosh 主機沒有 tmux 可供
  詢問，因此捲動起來就跟原版 mosh 一樣。
- **伺服器端的歷史。** 深度受伺服器上 tmux 的 `history-limit` 限制 —— Tessera
  只能顯示 tmux 保留下來的內容。
- **主畫面。** `vim`、`less`、`htop` 這類全螢幕程式會自行處理捲動；Tessera 會
  像所有終端機一樣，把你的捲動當成輸入轉送給它們。

## Mosh 與其他一切

對 mosh 主機而言，取回歷史的那條 SSH 側通道，同時也承載
[tmux 視窗與窗格](https://bambouville.com/docs/zh-hant/tmux/)和[連接埠轉發](https://bambouville.com/docs/zh-hant/port-forwarding/#mosh-與轉發)，而
[檔案面板](https://bambouville.com/docs/zh-hant/files/)會開啟它自己的 SSH 橋接 —— 因此檔案傳輸和通道在 mosh 和
純 SSH 上的表現完全相同。

有一點要注意：**mosh 的 UDP 無法穿過 SSH 跳板主機**。在
[經過跳板鏈的主機](https://bambouville.com/docs/zh-hant/connections/#跳板主機)上，Tessera 會先嘗試 mosh，若伺服器
在 UDP 上無法連線，就退回 SSH。至於本來就能經由 UDP 連到的目標 —— 例如透過
VPN 或 tailnet —— 仍會以 mosh 持續運作。
