診斷連接埠
本文適用於:✔️ .NET Core 3.1 與更新版本
.NET 執行階段可公開服務端點,允許其他處理序傳送診斷命令,並透過 IPC 通道接收回應。 此端點稱為「診斷連接埠」。 命令可以傳送至診斷連接埠,以:
- 擷取記憶體傾印。
- 啟動 EventPipe 追蹤。
- 要求用於啟動該應用程式的命令列。
診斷連接埠視平台之不同,支援不同的傳輸。 CoreCLR 和 Mono Runtime 實作目前在 Windows 上使用具名管道,而在 Linux 和 macOS 上使用 Unix 網域通訊端。 在 Android、iOS 和 tvOS 上的 Mono Runtime 實作,使用 TCP/IP。 該通道使用自訂二進位通訊協定。 大部分的開發人員永遠都不會直接與基礎通道和通訊協定進行互動,而是會使用代表其進行通訊的 GUI 或 CLI 工具。 例如,dotnet-dump 和 dotnet-trace 工具,會抽象化的傳送通訊協定命令,來擷取傾印以及啟動追蹤。 對於想要撰寫自訂工具的開發人員來說,Microsoft.Diagnostics.NETCore.Client NuGet 套件可提供基礎傳輸和通訊協定的 .NET API 抽象化。
安全性考量
診斷連接埠會公開執行中應用程式的敏感性資訊。 如果不受信任的使用者取得了此通道的存取權,他們即可觀察詳細的程式狀態,包括記憶體中的任何祕密,並可任意修改程式的執行。 CoreCLR Runtime 上的預設診斷連接埠,設定為只能由啟動該應用程式的相同使用者帳戶,或具有進階使用者權限的帳戶存取。 如果安全性模型不信任具有相同使用者帳戶認證的其他處理序,您可以藉由設定環境變數 DOTNET_EnableDiagnostics=0
來停用所有診斷連接埠。 這項設定會讓您無法使用外部工具,例如 .NET 偵錯或任何 dotnet-* 診斷工具。
注意
.NET 6 會針對設定 .NET Runtime 行為的環境變數,透過前置詞 DOTNET_
(而非 COMPlus_
) 進行標準化。 不過,COMPlus_
前置詞將繼續運作。 如果使用舊版的 .NET 執行階段,則您仍應對環境變數使用 COMPlus_
前置詞。
預設診斷連接埠
在 Windows、Linux 和 macOS 上,執行時間預設會在已知端點開啟一個診斷連接埠。 這是 dotnet-* 診斷工具在未明確地設定為使用替代連接埠時,會自動連線的連接埠。 端點為:
- Windows - 具名管道
\\.\pipe\dotnet-diagnostic-{pid}
- Linux 和 macOS - Unix 網域通訊端
{temp}/dotnet-diagnostic-{pid}-{disambiguation_key}-socket
{pid}
是以十進位撰寫的處理序識別碼,{temp}
是 TMPDIR
環境變數或為值 /tmp
(如果未定義 TMPDIR
或其為空白),{disambiguation_key}
則是以十進位撰寫的處理序開始時間。 在 macOS 和 NetBSD 上,處理序開始時間是自 UNIX epoch 以來的秒數。 而在所有其他平台上,則是自啟動時間起即為 jiffies。
在啟動時暫停執行階段
根據預設,不論任何診斷工具是否已連線到診斷連接埠,執行階段都會在啟動時立即執行受控程式碼。 有時候,很適合讓執行階段等到連線診斷工具之後,再執行受控程式碼以觀察初始程式行為。 設定環境變數 DOTNET_DefaultDiagnosticPortSuspend=1
可讓執行階段等到工具連線至預設連接埠為止。 如果幾秒後未附加任何工具,執行階段就會將警告訊息列印在主控台上,表示它仍在等待要附加工具。
設定其他診斷連接埠
注意
這僅適用於執行 .NET 5 或更新版本的應用程式。
Mono 和 CoreCLR 執行階段都可以在 connect
角色中使用自訂設定的診斷連接埠。 Mono 在 Android 或 iOS 上搭配 dotnet-dsrouter 使用時,也支援 listen
角色中的自訂 TCP/IP 連接埠。 除了仍可使用預設連接埠之外,還有這些自訂連接埠。 自訂連接埠很有用的幾個常見原因:
- 在 Android、iOS 和 tvOS 上沒有預設連接埠,因此必須設定連接埠才能使用診斷工具。
- 在有容器或防火牆的環境中,建議您設定一個可預測的端點位址,其不會像預設連接埠一樣,隨著處理序識別碼而更動。 然後,可以將自訂連接埠明確地新增至允許清單,或跨一些安全性界限,進行 Proxy 處理。
- 對於監視工具來說,讓工具接聽端點,而且讓執行階段主動嘗試連線到端點,會相當實用。 如此可避免需要監視工具來持續輪詢是否啟動了新的應用程式。 在無法存取預設診斷連接埠的環境中,它也同時避免掉需要對每個受監視的應用程式,為監視器設定自訂端點的作業。
在診斷工具和 .NET 執行階段之間的每個通道,一端必須是接聽程式,等候另一端的連線。 執行階段可以設定為以任何連接埠的 connect
角色執行動作。 (Mono 執行階段也可以設定為以任何連接埠的 listen
角色執行動作。)連接埠也可以獨立設定為在啟動時先暫停,等待診斷工具發出繼續的命令。 如果遠端端端點未接聽或連線遺失,設定為連線的連接埠會無限期地重複其連線嘗試。 但是應用程式在等候建立該連線時,不會自動暫止受控程式碼。 如果希望應用程式等候建立連線,請使用 [啟動時暫停] 選項。
自訂連接埠使用 DOTNET_DiagnosticPorts
環境變數加以設定。 此變數應設定為以分號分隔的連接埠描述清單。 每個連接埠描述都包含一個端點位址和選擇性的修飾元,可控制執行階段的 connect
或 listen
角色,以及啟動時是否應暫止該執行階段。 在 Windows 上,端點位址是沒有 \\.\pipe\
前置詞的具名管道名稱。 在 Linux 和 macOS 上,其會是 Unix 網域通訊端的完整路徑。 在 Android、iOS 和 tvOS 上,該位址是 IP 和連接埠。 例如:
DOTNET_DiagnosticPorts=my_diag_port1
- (Windows) 連線到具名管道\\.\pipe\my_diag_port1
的執行階段。DOTNET_DiagnosticPorts=/foo/tool1.socket;foo/tool2.socket
- (Linux 和 macOS) 同時連線到 Unix 網域通訊端/foo/tool1.socket
和/foo/tool2.socket
的執行階段。DOTNET_DiagnosticPorts=127.0.0.1:9000
- (Android、iOS 和 tvOS) 連線到連接埠 9000 上 IP 127.0.0.1 的執行階段。DOTNET_DiagnosticPorts=/foo/tool1.socket,nosuspend
- (Linux 和 macOS) 此範例有nosuspend
修飾元。 執行階段會嘗試連線到外部工具所建立的 Unix 網域通訊端/foo/tool1.socket
。 其他診斷連接埠一般會讓該執行階段在啟動時先暫停,以等候繼續的命令,但nosuspend
會讓該執行階段不等候。
連接埠的完整語法為 address[,(listen|connect)][,(suspend|nosuspend)]
。 如果皆未指定 connect
或 listen
,則 connect
為預設值 (且 listen
僅受 Android 或 iOS 上 Mono 執行階段的支援)。 如果未指定 suspend
或 nosuspend
,則預設值為 suspend
。
dotnet 診斷工具中的用法
dotnet-dump、dotnet-counters 和 dotnet-trace 等工具,都支援 collect
或 monitor
動詞,其透過診斷連接埠與 .NET 應用程式進行通訊。
- 當這些工具使用
--processId
引數時,此工具會自動計算預設診斷連接埠的位址,並連線該連接埠。 - 指定
--diagnostic-port
引數時,工具會接聽指定的位址,而您應使用DOTNET_DiagnosticPorts
環境變數,來設定您的應用程式進行連線。 如需 dotnet-counters 的完整範例,請參閱使用診斷連接埠。
使用 ds-router 來 Proxy 診斷連接埠
所有 dotnet-* 診斷工具都應該要連線到是本機具名管道或是 Unix 網域通訊端的診斷連接埠。 Mono 通常由獨立的硬體執行,或在需要透過 TCP 執行 Proxy 的模擬器中執行,才能變成可存取。 dotnet-dsrouter 工具可以將本機具名管道或 Unix 網域通訊端 Proxy 到 TCP,以讓這些環境內可以使用這些工具。 如需詳細資訊,請參閱 dotnet new。