arc network 回答一個問題:這臺機器能不能按 arc 需要的方式訪問外網?它只有一個子命令 doctor,跑四項檢查——代理發現、DNS、一次 HTTPS 請求、一次 WebSocket 握手——每一項單獨成行報告。分開報告是刻意的:"DNS 能解析但代理拒絕 CONNECT" 和 "什麼都解析不了" 是兩種不同的故障,修法也不同,一個籠統的通過/失敗會把你到底遇到哪一種給蓋住。
對照的是 arc 2.0.0-beta.48(構建 5a5316bde,2026-09-10)。單看版本號定不了這個——2.0.0-beta.48 這一輪週期裡已經指過不止一個二進位制——所以在相信下面任何輸出逐位元組一致之前,先跑一遍 arc --version,把它的第三個欄位(commit)跟上面這個對一下;檢查項和選項不管怎樣都可能在不同版本之間變化。
用法
arc network doctor [options]全域選項(見 總覽):--json、--view、--instance / -i(作用在哪個本地 ARC 例項;省略即 default),以及 --home(例項根;要指定作用在哪個例項,用 --instance)。doctor 不跟 daemon 打交道,所以有沒有 daemon 在跑它都能用。
--target <url>:要探測的 HTTPS URL(預設https://main.abtnetwork.io/)--ws-target <url>:要探測的 WSS URL(預設wss://main.abtnetwork.io/api/websocket?vsn=2.0.0)
arc network 單獨用不是一條命令:它會列印 Please specify a subcommand 和子命令列表,退出碼 5。
示例(一切可達,沒有代理)
$ arc network doctor
Outbound network doctor
Proxy:
(none)
Checks:
✓ proxy-discovery no proxy environment variables
✓ direct-dns main.abtnetwork.io → 198.18.0.38
✓ https-through-proxy HTTP 200 direct
✓ wss-through-proxy WSS handshake direct
OK四項全過,退出碼 0。那兩項網路檢查的名字裡始終帶著 through-proxy,哪怕根本沒有代理;真正告訴你走的是哪條路的是後面那一列——這裡是 direct。
direct-dns 那一行的地址,是你自己的解析器返回的結果,所以你看到的多半和這裡不同;在有劫持或過濾解析器的網路上,它甚至可能是這個域名其實並不擁有的地址。這不只是個腳註,因為失敗被歸到哪一層是跟著解析器走的:一個不存在的域名,在如實回答的解析器上報成 DNS 失敗,在照樣給出地址的解析器上則報成連線或 TLS 失敗。doctor 的結果讓你意外時,先用別的途徑獨立確認這個域名,再決定要不要相信是哪一項變紅了。
示例(配了代理,但代理不應答)
$ HTTPS_PROXY=http://127.0.0.1:9 HTTP_PROXY=http://127.0.0.1:9 arc network doctor
ERROR: Outbound network doctor
Proxy:
HTTP_PROXY http://127.0.0.1:9/
HTTPS_PROXY http://127.0.0.1:9/
Checks:
✓ proxy-discovery proxy environment variables present (credentials redacted)
✓ direct-dns main.abtnetwork.io → 198.18.0.38
✗ https-through-proxy PROXY_CONNECT_FAILED connect ECONNREFUSED 127.0.0.1:9
✗ wss-through-proxy PROXY_CONNECT_FAILED connect ECONNREFUSED 127.0.0.1:9
FAILED只要有檢查失敗,退出碼就是 5。第一行的 ERROR: 字首是 CLI 唯一的"這次執行失敗了"標記(arc#6301)——不管是哪條命令報的失敗,訊息都以同一種方式開頭,呼叫方不需要知道是哪條命令產出的,也能找到錯誤的開頭。注意看哪些還是綠的:代理發現過了,因為它只報告設了哪些變數,不報告代理能不能用;DNS 也過了,因為解析根本不走代理。失敗的那兩項寫出了原因——PROXY_CONNECT_FAILED——而不是一個籠統的超時,這正是讓你去查代理、而不是去查 DNS 或目標主機的依據。代理 URL 列印時裡面的憑據會被抹掉。
機器可讀的輸出
--json 把同一次執行輸出成結構化資料。下面用的是上面那次失敗的執行,因為有意思的欄位只在失敗時才出現:每個失敗的檢查會多出一個 code,而 required / affectsOverallHealth 說明結論是由哪些結果算出來的。這裡 direct-dns 翻成了 required: false——一旦走代理,能不能直連解析就不再是結論的依據了。
$ HTTPS_PROXY=http://127.0.0.1:9 HTTP_PROXY=http://127.0.0.1:9 arc network doctor --json
ERROR: {
"proxy": {
"httpProxy": "http://127.0.0.1:9/",
"httpsProxy": "http://127.0.0.1:9/"
},
"checks": [
{
"name": "proxy-discovery",
"ok": true,
"status": "pass",
"required": true,
"affectsOverallHealth": true,
"detail": "proxy environment variables present (credentials redacted)"
},
{
"name": "direct-dns",
"ok": true,
"status": "pass",
"required": false,
"affectsOverallHealth": false,
"detail": "main.abtnetwork.io → 198.18.0.38"
},
{
"name": "https-through-proxy",
"ok": false,
"status": "fail",
"required": true,
"affectsOverallHealth": true,
"code": "PROXY_CONNECT_FAILED",
"detail": "connect ECONNREFUSED 127.0.0.1:9"
},
{
"name": "wss-through-proxy",
"ok": false,
"status": "fail",
"required": true,
"affectsOverallHealth": true,
"code": "PROXY_CONNECT_FAILED",
"detail": "connect ECONNREFUSED 127.0.0.1:9"
}
],
"ok": false
}開頭那個 ERROR: 不是複製貼上錯了:失敗的執行裡,人類可讀示例裡同一個單一出口的字首,也會原樣出現在 JSON 前面,跟開頭的 { 擠在同一行——因為失敗命令的整條訊息,不管是人類文本還是 JSON,這個 CLI 在那個環節並不區分,都會被統一加上這一個標記。非零退出時先把這一個 token 剝掉再解析,或者乾脆按退出碼分支,不要去把 stderr 當 JSON 硬解析。乾淨的一次執行是同樣的形狀,只是沒有 code 欄位,每個 status 都是 pass,proxy 是空物件,頂層 ok 為 true——而且沒有 ERROR: 字首,因為它只在失敗時才出現。在你把這個接進管道之前還有一件事要知道:失敗的執行裡stdout 是 0 位元組——整條訊息,字首也算在內,都去了 stderr——所以 arc network doctor --json | jq 在失敗時什麼都看不到,不是看到一個錯誤物件;先查退出碼,不然你會去除錯自己的 jq 表示式,而不是真正的失敗。
兩個 target 是各管各的。--target 會同時改掉 HTTPS 探測和跟著它走的 DNS 檢查——探測 https://arc.arcblock.io/ 時 direct-dns 那行放的就是 arc.arcblock.io → …,不再是預設主機;而 --ws-target 只改 WebSocket 探測,DNS 仍然跟著 --target 走。所以把 --ws-target 指向一個關閉的連接埠,正好只有一項檢查會失敗:
$ arc network doctor --ws-target wss://127.0.0.1:9/
ERROR: Outbound network doctor
Proxy:
(none)
Checks:
✓ proxy-discovery no proxy environment variables
✓ direct-dns main.abtnetwork.io → 198.18.0.38
✓ https-through-proxy HTTP 200 direct
✗ wss-through-proxy UPSTREAM_REJECTED
FAILED這裡特意用了字面地址加一個關閉的連接埠,讓這個探測在任何機器上都以同樣的方式失敗——沒有域名要解析,也就沒有解析器可以有異議。真正點出是在哪一層失敗的是 code,也就是 UPSTREAM_REJECTED,跟 PROXY_CONNECT_FAILED / DIRECT_DNS_FAILED / TLS_FAILED 分得開;它後面那段自由文本的詳情並不保證一定有內容,這次抓到的就是空的——一次立即被拒絕的本機連線,沒能讓底層的 socket 層留下什麼話可說。不要去匹配這段詳情文本;要匹配 code,需要結構化就用 --json。當預設目標可達、但你真正關心的主機不可達時,就用這兩個選項。