使用 Term 時最常遇到的問題和解決辦法。
一個原因是切到背景。切走時,Term 會向系統申請一小段背景時間,最長 70 秒,在這段時間內回來,工作階段原封不動,接個電話、回覆一則訊息都不會中斷。系統實際給的額度可能更短(它自己的上限約 3 分鐘,低電量時約 1 分鐘),你一回到前景,這段背景時間就立即結束。超過這段時間之後,為了省電,HarmonyOS 會暫停長時間停留在背景的應用,連線隨之關閉:SSH 工作階段中斷,裏面正在執行的程式也會停止。
另一個原因是網絡變了,這一種連切背景都不需要,Term 可以一直好好地擺在螢幕上。普通 SSH(telnet 也一樣)是一條 TCP 連線,兩端各釘死在一個 IP 位址上:手機由 Wi-Fi 轉到 5G、走出路由器的覆蓋範圍、進電梯或者過隧道,位址一變、或者封包發不出去,這條連線就沒了,即使你全程都看着它。而且往往沒有任何提示,直到你按下一個鍵,發現沒有回顯。mosh 是唯一扛得住這個的傳輸方式:它走 UDP,認的是工作階段而不是位址,轉到新網絡上會自己接着跑。
以下是四種辦法。前三種是讓工作階段不中斷:由最簡單到最穩健;第四種是萬一還是斷了,怎樣回到原本的地方。
只要 Term 在螢幕上,工作階段就一直是活的。把它放進懸浮視窗或分割螢幕,它就算在前景:你可以同時用別的應用而不中斷。
在伺服器上執行 tmux(或 screen、zellij),最好再配合 mosh 連線。mosh 能承受網絡切換並自動重新連線,多工器則讓程式在伺服器上持續執行:隨時中斷、隨時回來,原地繼續。
sudo apt install tmux(Debian/Ubuntu)或 sudo dnf install tmux(Fedora)。tmux new -s work。tmux attach -t work,一切保持原樣。mosh-server),漫遊切換 Wi-Fi/行動網絡也不中斷。# 新增具名工作階段 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 … &。即使應用中斷連線,工作也會在伺服器上執行完,之後重新連線回來檢查結果即可。
# 脫離終端機背景執行,輸出寫入 out.log nohup ./long-task.sh > out.log 2>&1 & # 重新連線後查看進度 tail -f out.log
前面三種是讓工作階段不中斷。這一種承認它總有斷的時候(手機被暫停、網絡斷了),但仍然把你送回原本的工作現場。給主機設定一段啟動腳本,讓它接上多工器,腳本下方就會出現「自動恢復工作階段」開關:打開之後,跟著應用一起被結束的分頁會在下次啟動時重新打開,在背景待太久而被中斷的分頁會在你切回來時自動重連。
這裡沒有任何東西被「復活」,這一點值得說清楚:SSH 連線一旦斷開就是斷了,伺服器那邊沒有工作階段在等你。Term 做的是重新連上,真正保住你工作的是多工器,啟動腳本負責把你重新放回它裡面。所以只有當腳本確實會接上點甚麼,開關才會出現;只對 SSH 提供,預設關閉,而你自己關掉的分頁不會被接回來。
main。tmux new -A -s main 表示沒有就新建、有就接上,因此第一次連線和之後每一次都用同一行。# tmux:沒有就新建,有就接上 tmux new -A -s main # zellij zellij attach -c main
開一個具名工作階段,Term 會認出前景執行的是 tmux,把軟鍵盤上方的按鍵列換成一套 tmux 專用鍵:esc、^B 前綴、四個方向鍵,以及一批一按就送出的前綴組合。識別靠的是 Shell 整合回報的指令(預設開啟),所以別把它關掉。
tmux new -s work。^B[ 進入複製模式(回看歷史就靠它)、^Bz 放大目前窗格、^B% 與 ^B" 分割窗格、^Bc 新增視窗、^Bn / ^Bp 切換下一個 / 上一個視窗、^Bw 視窗清單、^Bd 脫離;^C 和 ^R 也在,畢竟底下還是個 shell 提示符。ctrl:它會為下一個按鍵加上 Ctrl 修飾(alt、shift 同理)。^Bd 脫離:工作階段和裏面正在執行的程式都留在伺服器上。tmux attach -t work 掛回去,一切保持原樣。
tail -12 ~/logs/app.log;最下面那條深色行是 tmux 自己的狀態列,左邊是工作階段名稱 work,中間是視窗 1:bash*,右邊是時鐘。頂部導覽列寫着的 tmux new -s work 就是 Shell 整合回報的指令,按鍵列正是據此切到 tmux 鍵集的。
^Bd 之後,tmux 打出 [detached (from session work)] 並把 shell 還給你;下一行的 tmux attach -t work 會把整個工作階段原樣接回來。先在伺服器上裝好 mosh,Term 要的是 mosh-server 這個程式。然後編輯主機,把連線方式選成 Mosh;應用裏那行提示已經把話說清楚了:登入仍然走 SSH,之後才把工作階段交給 UDP。所以伺服器那一側還要放行 UDP 60000–61000;若只開放了少數幾個 UDP 連接埠,也可以在主機編輯頁把 mosh 釘在這幾個連接埠上。連上之後,切換 Wi-Fi/行動網絡、訊號中斷都不會斷線,工作階段會自己重新連線,上面那條背景暫停的規矩,對 mosh 不適用。
UDP 60000–61000,不特別指定的話,mosh 會在這個範圍裏自己挑一個連接埠。只開放了特定連接埠的話,就在連線方式裏的「UDP 連接埠或範圍(選填)」填上:單一連接埠(60000)或一段範圍(60000:61000);留空就是自動挑。ps -o args= -p $PPID,shell 的父程序應該是 mosh-server,而不是 sshd。
# 安裝 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
ps -o args= -p $PPID 回答的是 mosh-server new -s -c 256 …:shell 的父程序是 mosh-server,不是 sshd,工作階段確實跑在 UDP 上。頂部導覽列也寫着 Sandbox (mosh)。因為 mosh 是直接重繪畫面,而不是逐行傳輸,根本沒有歷史可以給 Term 翻。這是 mosh 的設計,不是 Term 的限制。想回看,就在伺服器上執行 tmux(或 screen、zellij),用它自己的回捲:在 tmux 裏就是複製模式,也就是按鍵列上的 ^B[(見上面 tmux 那一節)。應用裏也會在原地說同一件事,首次連上 mosh 時的提示卡,以及在 mosh 工作階段裏第一次上滑時彈出的提示。
會。關閉 mosh 標籤頁時,Term 會發出 mosh 的關閉封包,結束伺服器上的那個工作階段;萬一這些封包沒能送到,它還會再用 SSH 連回去,把遺留的 mosh-server 收掉,基本不會在主機上留下孤兒程序。想稍後回來,就別關標籤頁。如果這份工作必須活得比標籤頁更久,那正是 tmux 的用處:在 mosh 工作階段裏執行 tmux,關掉標籤頁也只是脫離而已。
mosh 先用 SSH 登入,再把工作階段交給 UDP:這兩條錯誤分別對應其中一段出了問題,Term 會直接告訴你是哪一段。失敗畫面下方保留着原始錯誤和它的 E_ 代碼(回報問題時用得上),並給出編輯主機和重試兩個按鈕。
UDP 60000–61000。能,但 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”,圖片則悄無聲息地不出來。
# 放行圖像的跳脫序列 set -g allow-passthrough on # 在 tmux 內保持真彩色,否則圖像 id 會被改壞 set -as terminal-features ",*:RGB"
mosh 工作階段不受影響,它天然能在背景存活並自動重新連線,所以背景警告對它不適用。應用內也有同樣的說明:主機頁面的背景工作階段警告橫幅 → 點開「保持工作階段連線」說明頁。
參考: mosh.org · tmux 入門 · zellij · GNU screen · nohup(1)