‹ Term

常見問題

使用 Term 時最常遇到的問題和解決辦法。

工作階段為甚麼會中斷?

一個原因是切到背景。切走時,Term 會向系統申請一小段背景時間,最長 70 秒,在這段時間內回來,工作階段原封不動,接個電話、回覆一則訊息都不會中斷。系統實際給的額度可能更短(它自己的上限約 3 分鐘,低電量時約 1 分鐘),你一回到前景,這段背景時間就立即結束。超過這段時間之後,為了省電,HarmonyOS 會暫停長時間停留在背景的應用,連線隨之關閉:SSH 工作階段中斷,裏面正在執行的程式也會停止。

另一個原因是網絡變了,這一種連切背景都不需要,Term 可以一直好好地擺在螢幕上。普通 SSH(telnet 也一樣)是一條 TCP 連線,兩端各釘死在一個 IP 位址上:手機由 Wi-Fi 轉到 5G、走出路由器的覆蓋範圍、進電梯或者過隧道,位址一變、或者封包發不出去,這條連線就沒了,即使你全程都看着它。而且往往沒有任何提示,直到你按下一個鍵,發現沒有回顯。mosh 是唯一扛得住這個的傳輸方式:它走 UDP,認的是工作階段而不是位址,轉到新網絡上會自己接着跑。

以下是四種辦法。前三種是讓工作階段不中斷:由最簡單到最穩健;第四種是萬一還是斷了,怎樣回到原本的地方。

方法一 · 保持 Term 在前景

只要 Term 在螢幕上,工作階段就一直是活的。把它放進懸浮視窗或分割螢幕,它就算在前景:你可以同時用別的應用而不中斷。

  1. 懸浮視窗:從螢幕底部上滑並停頓,進入最近任務介面;點 Term 卡片上的懸浮視窗圖示,終端機會縮成一個可拖動的小視窗。
  2. 分割螢幕:同樣在最近任務介面,點 Term 卡片上的分割螢幕圖示,再選擇另一個應用並排顯示。
  3. 掛着工作階段去查資料、回訊息,回來繼續輸入:連線從未中斷。
方法二 · Mosh + 多工器推薦

在伺服器上執行 tmux(或 screen、zellij),最好再配合 mosh 連線。mosh 能承受網絡切換並自動重新連線,多工器則讓程式在伺服器上持續執行:隨時中斷、隨時回來,原地繼續。

  1. 在伺服器上安裝 tmux:sudo apt install tmux(Debian/Ubuntu)或 sudo dnf install tmux(Fedora)。
  2. 用 Term 連上主機,新增一個具名工作階段:tmux new -s work。
  3. 在裏面正常工作:即使手機鎖定螢幕、切背景、斷網,工作階段都留在伺服器上。
  4. 重新連線後掛回去:tmux attach -t work,一切保持原樣。
  5. 更進一步:新增主機時把連線方式選為 mosh(伺服器需安裝 mosh-server),漫遊切換 Wi-Fi/行動網絡也不中斷。
tmux — 伺服器上
# 新增具名工作階段
tmux new -s work

# 重新連線之後掛回去
tmux attach -t work

預設設定的 tmux 會悄悄吞掉不少 Term 能做的事(內嵌圖片、剪貼簿、帶修飾鍵的組合鍵),而且它不會報錯,只是沒反應。所以值得設定一次。我們用來測試 Term 的那份設定有專門一頁,每一行都有註解,還有一鍵複製整份的按鈕。其中有一行正是為這一節寫的:tmux 發剪貼簿 OSC 52 時不填目標,而 mosh 只轉發 52;c; 這一種寫法,沒有那行 terminal-overrides 去糾正,你在 tmux 裏複製的內容只會落進 tmux 自己的貼上緩衝區,根本出不了伺服器。其中兩行跟圖片有關的設定,本頁下面還有一節專門講。

逐行講這份設定:我們在用的 tmux 設定

方法三 · 長時間工作放到背景執行

耗時工作讓它脫離終端機執行:在 tmux/screen 裏啟動,或者用 nohup … &。即使應用中斷連線,工作也會在伺服器上執行完,之後重新連線回來檢查結果即可。

nohup — 伺服器上
# 脫離終端機背景執行,輸出寫入 out.log
nohup ./long-task.sh > out.log 2>&1 &

# 重新連線後查看進度
tail -f out.log
方法四 · 讓 Term 把工作階段接回來
v26.1.0+

前面三種是讓工作階段不中斷。這一種承認它總有斷的時候(手機被暫停、網絡斷了),但仍然把你送回原本的工作現場。給主機設定一段啟動腳本,讓它接上多工器,腳本下方就會出現「自動恢復工作階段」開關:打開之後,跟著應用一起被結束的分頁會在下次啟動時重新打開,在背景待太久而被中斷的分頁會在你切回來時自動重連。

這裡沒有任何東西被「復活」,這一點值得說清楚:SSH 連線一旦斷開就是斷了,伺服器那邊沒有工作階段在等你。Term 做的是重新連上,真正保住你工作的是多工器,啟動腳本負責把你重新放回它裡面。所以只有當腳本確實會接上點甚麼,開關才會出現;只對 SSH 提供,預設關閉,而你自己關掉的分頁不會被接回來。

  1. 伺服器上先裝好 tmux,並想好要常駐的工作階段名稱:下面用的是 main。
  2. 編輯主機 → 進階選項 → 「啟動腳本」,填一段會接上工作階段的指令:tmux new -A -s main 表示沒有就新建、有就接上,因此第一次連線和之後每一次都用同一行。
  3. 欄位正下方會出現「自動恢復工作階段」開關,打開並儲存。
  4. 就這些。開著分頁把應用結束掉,下次啟動它會回來;把 Term 丟在背景直到連線中斷,切回來時它會自己重連。
可以觸發開關的啟動腳本
# tmux:沒有就新建,有就接上
tmux new -A -s main

# zellij
zellij attach -c main

想了解更多:會自己接回來的 SSH 工作階段:甚麼能恢復、甚麼不能

在手機上怎樣用 tmux?

開一個具名工作階段,Term 會認出前景執行的是 tmux,把軟鍵盤上方的按鍵列換成一套 tmux 專用鍵:esc、^B 前綴、四個方向鍵,以及一批一按就送出的前綴組合。識別靠的是 Shell 整合回報的指令(預設開啟),所以別把它關掉。

  1. 連上主機,新增具名工作階段:tmux new -s work。
  2. 按鍵列隨即換成 tmux 鍵集:^B[ 進入複製模式(回看歷史就靠它)、^Bz 放大目前窗格、^B% 與 ^B" 分割窗格、^Bc 新增視窗、^Bn / ^Bp 切換下一個 / 上一個視窗、^Bw 視窗清單、^Bd 脫離;^C 和 ^R 也在,畢竟底下還是個 shell 提示符。
  3. 這一套是內建的,跟着前景程式自動切換,不需要你設定甚麼。需要別的控制鍵時,點一下按鍵列最左邊的 ctrl:它會為下一個按鍵加上 Ctrl 修飾(alt、shift 同理)。
  4. 離開時按 ^Bd 脫離:工作階段和裏面正在執行的程式都留在伺服器上。
  5. 下次連上來 tmux attach -t work 掛回去,一切保持原樣。
一個 tmux 工作階段上下分成兩個窗格:上面執行 htop,下面是 tail 打出的日誌;最底部是 tmux 自己的狀態列。
tmux 分割窗格,上下兩個窗格:htop 和 tail -12 ~/logs/app.log;最下面那條深色行是 tmux 自己的狀態列,左邊是工作階段名稱 work,中間是視窗 1:bash*,右邊是時鐘。頂部導覽列寫着的 tmux new -s work 就是 Shell 整合回報的指令,按鍵列正是據此切到 tmux 鍵集的。
終端機裏的兩行:tmux 打出的 [detached (from session work)],下一行是已經輸入 tmux attach -t work 的提示符。
脫離,再掛回去:按下 ^Bd 之後,tmux 打出 [detached (from session work)] 並把 shell 還給你;下一行的 tmux attach -t work 會把整個工作階段原樣接回來。
怎樣用 mosh 連線?

先在伺服器上裝好 mosh,Term 要的是 mosh-server 這個程式。然後編輯主機,把連線方式選成 Mosh;應用裏那行提示已經把話說清楚了:登入仍然走 SSH,之後才把工作階段交給 UDP。所以伺服器那一側還要放行 UDP 60000–61000;若只開放了少數幾個 UDP 連接埠,也可以在主機編輯頁把 mosh 釘在這幾個連接埠上。連上之後,切換 Wi-Fi/行動網絡、訊號中斷都不會斷線,工作階段會自己重新連線,上面那條背景暫停的規矩,對 mosh 不適用。

  1. 在伺服器上安裝:mosh 各家發行版基本都打了包,通常一行就夠;下面程式碼區塊裏按系統列了對應的指令,也包括 macOS。RHEL、Rocky、AlmaLinux 上它在 EPEL 裏,得先啟用 EPEL。
  2. 在 Term 裏編輯這台主機 → 連線方式 → 選 Mosh。主機、連接埠、使用者名稱照舊填 SSH 那一套,登入本來就還是走 SSH。
  3. 放行伺服器(以及中間鏈路)上的 UDP 60000–61000,不特別指定的話,mosh 會在這個範圍裏自己挑一個連接埠。只開放了特定連接埠的話,就在連線方式裏的「UDP 連接埠或範圍(選填)」填上:單一連接埠(60000)或一段範圍(60000:61000);留空就是自動挑。
  4. 想確認真的走在 mosh 上:連上後執行 ps -o args= -p $PPID,shell 的父程序應該是 mosh-server,而不是 sshd。
主機編輯頁的「連線方式」卡片,分段控制項 SSH / Mosh / Telnet 中 Mosh 處於選取狀態。
連線方式 · Mosh,主機編輯頁裏的分段控制項(SSH / Mosh / Telnet),選中 Mosh。上面「伺服器」卡片裏的主機、連接埠、使用者名稱照舊是 SSH 那一套。下面那行是應用自己的提示:主機需要裝 mosh-server,登入仍透過 SSH 完成。
mosh — 伺服器上
# 安裝 mosh:Term 要的是裏面的 mosh-server
sudo apt install mosh     # Debian / Ubuntu
sudo dnf install mosh     # Fedora / RHEL
sudo pacman -S mosh       # Arch
sudo zypper install mosh  # openSUSE
sudo apk add mosh         # Alpine
brew install mosh         # macOS (Homebrew)
sudo pkg install mosh     # FreeBSD

# 確認 shell 的父程序真的是 mosh-server
ps -o args= -p $PPID
一個 mosh 工作階段裏,ps -o args= -p $PPID 的輸出是 mosh-server new -s -c 256 -l LANG=en_US.UTF-8。
確認走的是 mosh,ps -o args= -p $PPID 回答的是 mosh-server new -s -c 256 …:shell 的父程序是 mosh-server,不是 sshd,工作階段確實跑在 UDP 上。頂部導覽列也寫着 Sandbox (mosh)。

想再深一步:Mosh 進階設定:連接埠、工作階段逾時、初始化指令碼

mosh 工作階段為甚麼不能回捲?

因為 mosh 是直接重繪畫面,而不是逐行傳輸,根本沒有歷史可以給 Term 翻。這是 mosh 的設計,不是 Term 的限制。想回看,就在伺服器上執行 tmux(或 screen、zellij),用它自己的回捲:在 tmux 裏就是複製模式,也就是按鍵列上的 ^B[(見上面 tmux 那一節)。應用裏也會在原地說同一件事,首次連上 mosh 時的提示卡,以及在 mosh 工作階段裏第一次上滑時彈出的提示。

關閉 mosh 標籤頁會結束工作階段嗎?

會。關閉 mosh 標籤頁時,Term 會發出 mosh 的關閉封包,結束伺服器上的那個工作階段;萬一這些封包沒能送到,它還會再用 SSH 連回去,把遺留的 mosh-server 收掉,基本不會在主機上留下孤兒程序。想稍後回來,就別關標籤頁。如果這份工作必須活得比標籤頁更久,那正是 tmux 的用處:在 mosh 工作階段裏執行 tmux,關掉標籤頁也只是脫離而已。

「mosh-server 未啟動」/「UDP 工作階段未能建立」

mosh 先用 SSH 登入,再把工作階段交給 UDP:這兩條錯誤分別對應其中一段出了問題,Term 會直接告訴你是哪一段。失敗畫面下方保留着原始錯誤和它的 E_ 代碼(回報問題時用得上),並給出編輯主機和重試兩個按鈕。

  1. 已連線,但 mosh-server 未啟動。 登入那一步是成功的,缺的是程式本身:在伺服器上安裝 mosh,或者把這台主機改回 SSH。
  2. 已透過 SSH 連線,但 mosh 的 UDP 工作階段未能建立。 mosh-server 起來了,封包卻沒到:放行伺服器以及中間鏈路上的 UDP 60000–61000。
tmux 裏能顯示內嵌圖片嗎?

能,但 tmux.conf 裏要加兩行。Term 原生解碼 sixel、kitty 圖形協定和 iTerm2 的 imgcat(OSC 1337)(PNG、JPEG 以及 GIF 的第一幀),並把圖像合成在文字下層。要穿過 tmux,圖像走的是 kitty 的 Unicode 佔位符方案:圖像 id 藏在字元格的真彩色前景色裏。所以 tmux 一要放行這段跳脫序列,二要在內部保持真彩色,少了第二條,tmux 會把帶 id 的顏色降到 256 色,id 被改壞,圖也就廢了。這兩行都需要 tmux 3.3a 或更新的版本,版本太舊的話,tmux 啟動時只會報 “unknown option”,圖片則悄無聲息地不出來。

~/.tmux.conf
# 放行圖像的跳脫序列
set -g allow-passthrough on

# 在 tmux 內保持真彩色,否則圖像 id 會被改壞
set -as terminal-features ",*:RGB"
備註與參考

mosh 工作階段不受影響,它天然能在背景存活並自動重新連線,所以背景警告對它不適用。應用內也有同樣的說明:主機頁面的背景工作階段警告橫幅 → 點開「保持工作階段連線」說明頁。

參考: mosh.org · tmux 入門 · zellij · GNU screen · nohup(1)