先釐清:系統代理 ≠ 終端機一定會跟著走
在 macOS 上,「系統設定」裡的 Wi-Fi 代理、或 Clash/Mihomo 系用戶端一鍵開啟的系統代理,主要影響的是願意呼叫系統代理 API 的圖形介面程式與部分內建服務。相對地,終端機裡執行的 curl、git、brew 等工具,多半不會自動去讀 macOS 的系統代理面板,而是看它們自己的設定檔、以及當前行程繼承到的環境變數(例如 http_proxy、HTTPS_PROXY)。
因此,你會看到一種非常典型、卻讓人困惑的現象:瀏覽器顯示 IP 已變,下載外掛也正常,但命令列一測卻像完全沒開代理。這不代表 Clash 核心沒在聽本機埠,而是該行程根本沒有被設定成要把 HTTP/HTTPS 交給本機代理。接下來我們會用「可重現」的順序,把變數從哪裡來、誰會讀、以及哪裡會被覆寫,一次攤開來對照。
若你希望連同系統底層流量都納入同一套路由決策,也可以延伸閱讀本站另一篇以 TUN 為主題的說明,理解虛擬網卡接管與僅設系統代理在覆蓋面上的差異,避免把兩種層次混在同一個除錯假設裡。Clash TUN 模式完全指南整理了觀念與常見漏流情境,可作為進階對照。
第一步:確認你當下是「哪一個 Shell」、是否為登入 Shell
同一份寫在 ~/.zshrc 的設定,可能在你開啟「終端機 App」時有載入,在 VS Code 內建終端機、或 SSH 連進遠端時卻完全沒載入,原因常常是登入(login)與非登入(non-login)互動 Shell 的啟動檔規則不同。在排查代理變數時,請先在出問題的那個終端機視窗裡執行:
echo "$SHELL"
echo "$0"
ps -p $$ -o comm=
若你預期使用 zsh,卻發現某些情境其實落在 bash 或 sh,就要改去對應的啟動檔(例如 ~/.bash_profile、~/.bashrc)找代理相關行,而不是只在 .zshrc 裡打轉。另一個實務技巧是:在設定檔開頭加一行僅用於除錯的標記輸出(完成排查後務必移除),確認目前這個視窗載入的究竟是哪一條路徑上的檔案。
Apple 預設登入殼層在近年版本多為 zsh;但若你透過套件管理器或公司腳本改過預設 Shell,仍可能出現「圖形終端機是 zsh、某 IDE 內建終端機卻繼承舊環境」的落差。這一步的目的很單純:先鎖定「誰在跑」,後面討論 http_proxy 才有意義,否則你改的是 A Shell 的設定,實際執行 brew 的卻是 B Shell 啟動的環境。
第二步:檢查 http_proxy、HTTPS_PROXY、ALL_PROXY 與大小寫
多數命令列 HTTP 用戶端會依序參考數個變數名稱,且大小寫靈敏度依實作而異。實務上建議同時設定小寫與大寫兩組,降低「某工具只讀大寫、另一個只讀小寫」的邊角案例。你可以在終端機直接執行:
env | grep -i proxy
若輸出為空,或只有殘留舊值,就要回頭找是誰在啟動時清空/覆寫。常見合理寫法(埠號請改為你在 Clash 用戶端看到的本機 HTTP 或 mixed 埠;以下僅示意):
export http_proxy="http://127.0.0.1:7890"
export https_proxy="http://127.0.0.1:7890"
export HTTP_PROXY="$http_proxy"
export HTTPS_PROXY="$https_proxy"
export all_proxy="socks5://127.0.0.1:7891"
export ALL_PROXY="$all_proxy"
重點在於協定前綴與埠號必須與 Clash 實際監聽一致。若你啟用的是 mixed port,通常一個埠可同時承載 HTTP 與 SOCKS,但仍要以用戶端介面與設定檔為準;把 https_proxy 指到一個「只提供 SOCKS、卻用 http:// 前綴描述」的組合,可能導致部分工具靜默失敗或退回直連。建議以用戶端顯示的「本機連接埠說明」為單一真相來源,必要時搭配連線日誌觀察是否有本機連入。
另外,請留意子行程繼承:你在 A 視窗 export 過,B 視窗不會自動有;若使用 launchd、GUI App 啟動的腳本、或 CI 工作區,也要看它們的環境是否另行注入。macOS Clash 終端代理問題,十之八九卡在「以為設過一次就全域生效」,其實只是當次 Session 有效。
第三步:對照 zsh 會讀哪些檔案(.zshenv、.zprofile、.zshrc)
對多數使用者而言,zsh 的載入順序可以粗略記成:所有 zsh 都會嘗試載入 ~/.zshenv;登入 Shell 還會讀 ~/.zprofile(與系統層 /etc/zprofile);互動 Shell 再讀 ~/.zshrc。因此,若你只在 .zshrc 設代理,卻在某個「非互動、或非登入」情境執行指令,就可能出現變數缺席。
實務建議是:把「讓命令列工具穩定看見代理」的 export 放在會被目標情境載入的檔案。舉例來說,若你希望從「圖形介面啟動的終端機」到「遠端 SSH 登入」都一致,常會考慮 .zprofile 或 .zshenv;但若擔心 .zshenv 影響過廣,可優先放在 .zprofile 並用實際開窗測試驗證。請避免在多個檔案重複設定卻彼此矛盾──後載入的檔案若沒有統一管理,很容易出現「有時有代理、有時被設回空字串」的詭異現象。
若你使用 Oh My Zsh 等框架,還要檢查外掛或主題是否在啟動流程中改寫環境。排查時可暫時以 zsh -f 啟動乾淨 Shell,對照有無載入自訂設定時的差異,快速鎖定是否為外掛鏈造成 HTTPS_PROXY 被清空。
第四步:確認 Clash 本機 HTTP/SOCKS 埠與 Mixed Port
Clash 系核心會在本機開啟一個或多個連接埠:常見包括 HTTP 代理埠、SOCKS5 埠,以及將兩者合併的 mixed port。終端機環境變數必須指向目前正在監聽、且協定相符的那個埠。若你升級用戶端或匯入新設定後改了埠號,但 .zshrc 仍寫舊的 7890,就會出現「Clash 其實在聽 7897,命令列卻連到錯誤埠」的狀況。
建議在用戶端介面確認三件事:第一,本機代理是否啟用;第二,埠號與允許來自區域網路等選項是否符合你的使用情境(僅本機終端機通常只需綁定 127.0.0.1);第三,若同時啟用 TUN 或公司 VPN,是否出現僅部分介面可走本機埠的路由特例。若你希望命令列與圖形程式一律走核心決策,可評估 TUN 與 DNS 搭配;前述 TUN 模式指南可作為是否採用該路線的參考。
最後,請不要用「感覺連得上」代替驗證。建議在設定變數後,用最小指令測試:例如對一個已知需代理才會成功的 HTTPS 端點發請求,並對照 Clash 連線日誌是否出現對應記錄。若日誌完全沒有該連線,代表請求沒進核心;若有記錄但顯示 DIRECT,則要回到規則與策略組,而不是繼續調環境變數。
第五步:檢查 no_proxy/NOPROXY 與區網例外是否排除過寬
許多公司腳本或舊教學會設定類似 no_proxy=localhost,127.0.0.1,10.0.0.0/8,.local 的例外清單,以避免內網流量誤走代理。問題在於:若清單寫得過寬,或複製貼上時帶入額外網域後綴,可能導致你以為會走代理的目標,其實命中例外而直連。
請在終端機檢查:
echo "$no_proxy"
echo "$NO_PROXY"
若你發現某些網址怎麼樣都不走代理,可暫時在測試用子 Shell內取消 no_proxy 再試一次,藉此二分法確認是否為例外清單所致。完成測試後請還原,避免把內網流量誤送到不相干出口。
另一個與 macOS 特別相關的細節是:部分工具會把 *.cn 或特定頂級域寫進例外,與你的分流意圖衝突。建議把「例外清單」視為與規則集同等敏感的設定,變更時記錄原因與日期,未來才追得回來。
Homebrew、Git、cURL 的行為差異與快速對照
Homebrew 在下載套件與更新時會使用網路堆疊;一般會繼承終端機的代理環境變數,但若你透過不同使用者、或從非互動環境觸發(例如某些自動化排程),仍可能出現變數缺失。若 brew 明確報錯連線逾時,先回到本文第二節確認變數,再檢查是否被公司防火牆攔截對 GitHub/CDN 的連線。
Git 除了環境變數外,還可能受 git config --global http.proxy 影響;若曾設定過固定代理,後續即使 https_proxy 正確,仍可能走舊值或與變數互相覆蓋。可用 git config --global --get http.proxy 與 https.proxy 查閱,並以版本庫需求決定是否清空或改指向本機 Clash 埠。
cURL 對代理的解析順序與選項較細:除環境變數外,命令列上的 -x/--proxy 往往優先。若你腳本裡硬編了 --noproxy '*' 之類選項,也會讓環境變數失效。建議以「同一條測試指令、只改一個變因」的方式驗證,而不是同時改設定檔又改 Shell。
與 TUN、系統代理併用時的觀念整理
有些使用者會同時開啟 TUN 與終端機代理變數,或在用戶端裡開著「系統代理」又手動 export。一般情況下,只要路由與規則沒有互相打架,這樣做未必錯,但會讓除錯變難:你不容易判斷某條連線究竟是經由虛擬網卡、還是經由 HTTP 代理埠。建議在排查時採單一變因:先固定 Clash 規則與節點可用,再決定本次要以「純環境變數」或「純 TUN」其中一條路徑驗證。
若你確認只要瀏覽器與少數圖形程式走代理即可,終端機維持直連是可接受的選擇;但若長期需要在終端機操作套件管理、同步原始碼、呼叫 API,那麼把代理變數納入標準 Shell 啟動流程,通常比每次手動輸入 export 更穩定。整體而言,macOS Clash 終端代理的本質是:讓命令列行程看見一致、正確、可繼承的出站路徑資訊。
可列印檢查清單:從現在這個視窗開始
總結成一份你可以照抄順序操作的清單:① 在出問題的視窗確認 Shell 類型;② env | grep -i proxy 檢查大小寫與是否為空;③ 依 Shell 類型打開對應啟動檔,確認 export 是否在正確檔案、且無互相覆寫;④ 對照 Clash 用戶端確認本機埠與協定;⑤ 檢查 no_proxy 是否過寬;⑥ 針對 brew/git/curl 分別做單一工具的最小重現測試。只要每一步都有「預期結果」與「實際結果」,你很快就能定位是環境、工具,還是規則層的問題。
更進階的文件與平台下載入口,可一併收藏本站使用說明與文件,把終端機代理與用戶端圖形介面設定放在同一套知識架構裡維護;需要安裝或更新用戶端時,請優先使用用戶端下載頁取得對應平台版本,避免在發布頁眾多檔名中混淆架構與簽章資訊。
結語:把「可驗證」當習慣,就不怕命令列突然直連
相較於只依賴系統代理面板,終端機世界更吃明確的環境變數與可重現的啟動順序。當你把 http_proxy、HTTPS_PROXY、ALL_PROXY 與 no_proxy 都納入版本控管或備註良好的設定檔,未來無論換機、升級 macOS、或更換 Clash 用戶端,都能用同一套步驟快速驗證,而不是每次從零開始猜。
若你希望圖形程式與命令列工具都能在清楚介面下完成設定,並在需要時銜接 TUN、規則集與日誌排查,選擇文件完整、更新節奏穩定的 Clash 系用戶端,通常比散落各處的過期腳本更省時間。相比僅靠一次性教學,持續維護可驗證的環境,長期成本反而更低。