Diagnostické porty

Tento článek se vztahuje na: ✔️ .NET Core 3.1 a novější verze

Modul runtime .NET zveřejňuje koncový bod služby, který umožňuje jiným procesům odesílat diagnostické příkazy a přijímat odpovědi přes kanál IPC. Tento koncový bod se nazývá diagnostický port. Příkazy se dají odeslat na port diagnostiky do:

  • Zachyťte výpis paměti.
  • Spusťte trasování EventPipe .
  • Požádejte o příkazový řádek použitý ke spuštění aplikace.

Diagnostický port podporuje různé přenosy v závislosti na platformě. V současné době implementace CoreCLR i Mono runtime používají pojmenované kanály ve Windows a Unix Domain Sockets v Linuxu a macOS. Implementace mono modulu runtime v systémech Android, iOS a tvOS používá protokol TCP/IP. Kanál používá vlastní binární protokol. Většina vývojářů nebude nikdy přímo komunikovat s podkladovým kanálem a protokolem, ale místo toho bude používat grafické uživatelské rozhraní nebo nástroje rozhraní příkazového řádku, které komunikují jejich jménem. Například nástroje dotnet-dump a dotnet-trace abstrahují odesílání příkazů protokolu za účelem zachycení výpisů a spuštění trasování. Pro vývojáře, kteří chtějí psát vlastní nástroje, balíček NuGet Microsoft.Diagnostics.NETCore.Client poskytuje abstrakci rozhraní .NET API základního přenosu a protokolu.

Bezpečnostní aspekty

Diagnostický port zveřejňuje citlivé informace o spuštěné aplikaci. Pokud nedůvěryhodný uživatel získá přístup k tomuto kanálu, může sledovat podrobný stav programu, včetně všech tajných kódů, které jsou v paměti, a libovolně upravit provádění programu. V modulu runtime CoreCLR je výchozí diagnostický port nakonfigurovaný tak, aby byl přístupný jenom pomocí stejného uživatelského účtu, který spustil aplikaci nebo účet s oprávněními superuživatele. Pokud váš model zabezpečení nedůvěřuje jiným procesům se stejnými přihlašovacími údaji uživatelského účtu, můžete zakázat všechny diagnostické porty nastavením proměnné DOTNET_EnableDiagnostics=0prostředí . Toto nastavení zablokuje možnost používat externí nástroje, jako je ladění .NET nebo jakýkoli z diagnostických nástrojů dotnet-*.

Poznámka:

.NET 6 standardizuje předponu DOTNET_ místo COMPlus_ proměnných prostředí, které konfigurují chování za běhu .NET. Předpona COMPlus_ ale bude i nadále fungovat. Pokud používáte předchozí verzi modulu runtime .NET, měli byste stále používat předponu COMPlus_ pro proměnné prostředí.

Výchozí diagnostický port

V systému Windows, Linux a macOS má modul runtime ve výchozím nastavení otevřený jeden diagnostický port v dobře známém koncovém bodu. Jedná se o port, ke kterému se diagnostické nástroje dotnet-* připojují automaticky, když nejsou explicitně nakonfigurované tak, aby používaly alternativní port. Koncový bod je:

  • Windows – pojmenovaný kanál \\.\pipe\dotnet-diagnostic-{pid}
  • Linux a macOS – Unix Domain Socket {temp}/dotnet-diagnostic-{pid}-{disambiguation_key}-socket

{pid} je ID procesu napsané v desítkové soustavě, {temp} je TMPDIR proměnná prostředí nebo hodnota /tmp , pokud TMPDIR není definována nebo prázdná, a {disambiguation_key} jedná se o počáteční čas procesu napsaný v desítkové soustavě. V systému macOS a NetBSD je počáteční čas procesu počet sekund od systém UNIX epochy. Na všech ostatních platformách je to od doby spuštění jiffies.

Pozastavení modulu runtime při spuštění

Modul runtime ve výchozím nastavení spustí spravovaný kód hned po spuštění bez ohledu na to, jestli se k diagnostickému portu připojily nějaké diagnostické nástroje. Někdy je užitečné, aby modul runtime čekal na spuštění spravovaného kódu až po připojení diagnostického nástroje, aby bylo možné sledovat chování počátečního programu. Nastavení proměnné DOTNET_DefaultDiagnosticPortSuspend=1 prostředí způsobí, že modul runtime počká, dokud se nástroj připojí k výchozímu portu. Pokud po několika sekundách není žádný nástroj připojený, modul runtime vypíše do konzoly upozornění s vysvětlením, že stále čeká na připojení nástroje.

Konfigurace dalších diagnostických portů

Poznámka:

Funguje to jenom pro aplikace, na kterých běží .NET 5 nebo novější.

Moduly runtime Mono i CoreCLR můžou v connect roli používat vlastní nakonfigurované diagnostické porty. Mono také podporuje vlastní porty TCP/IP v listen roli při použití s dotnet-dsrouter v Androidu nebo iOSu. Tyto vlastní porty jsou navíc k výchozímu portu, který zůstává dostupný. Existují některé běžné důvody, proč jsou vlastní porty užitečné:

  • V Androidu, iOSu a tvOSu není žádný výchozí port, takže konfigurace portu je nezbytná pro použití diagnostických nástrojů.
  • V prostředích s kontejnery nebo branami firewall můžete chtít nastavit předvídatelnou adresu koncového bodu, která se liší podle ID procesu, jak to dělá výchozí port. Potom můžete vlastní port explicitně přidat do seznamu povolených nebo přesxisovat přes určitou hranici zabezpečení.
  • Pro monitorovací nástroje je užitečné, aby nástroj naslouchal na koncovém bodu a modul runtime se k němu aktivně pokouší připojit. Díky tomu nemusíte nástroj pro monitorování průběžně dotazovat na nové aplikace. V prostředích, kde není výchozí diagnostický port přístupný, se také vyhne nutnosti konfigurovat monitorování s vlastním koncovým bodem pro každou monitorovanou aplikaci.

V každém komunikačním kanálu mezi diagnostickým nástrojem a modulem runtime .NET musí být jedna strana naslouchacím procesem a čekat na připojení druhé strany. Modul runtime je možné nakonfigurovat tak, aby fungoval v connect roli pro libovolný port. (Modul runtime Mono lze také nakonfigurovat tak, aby fungoval v listen roli pro libovolný port.) Porty je také možné nezávisle nakonfigurovat tak, aby se pozastavily při spuštění, a čekat na vydání příkazu pro obnovení diagnostickým nástrojem. Porty nakonfigurované pro připojení opakují pokusy o připojení po neomezenou dobu, pokud vzdálený koncový bod nenaslouchá nebo dojde ke ztrátě připojení. Aplikace ale při čekání na navázání připojení automaticky nespusí spravovaný kód. Pokud chcete, aby aplikace čekala na navázání připojení, použijte možnost pozastavení při spuštění.

Vlastní porty se konfigurují pomocí DOTNET_DiagnosticPorts proměnné prostředí. Tato proměnná by měla být nastavena na seznam popisů portů oddělených středníkem. Každý popis portu se skládá z adresy koncového bodu a volitelných modifikátorů, které řídí modul runtime connect nebo listen roli a pokud by měl modul runtime při spuštění pozastavit. Ve Windows je adresa koncového bodu název pojmenovaného kanálu bez předpony \\.\pipe\ . V Linuxu a macOS je to úplná cesta k rozhraní UNIX Domain Socket. V Androidu, iOSu a tvOSu je adresa IP a port. Příklad:

  1. DOTNET_DiagnosticPorts=my_diag_port1 - (Windows) Modul runtime se připojí k pojmenované kanálu \\.\pipe\my_diag_port1.
  2. DOTNET_DiagnosticPorts=/foo/tool1.socket;foo/tool2.socket - (Linux a macOS) Modul runtime se připojuje k rozhraní UNIX Domain Sockets /foo/tool1.socket i /foo/tool2.socket.
  3. DOTNET_DiagnosticPorts=127.0.0.1:9000 – (Android, iOS a tvOS) Modul runtime se připojí k IP adrese 127.0.0.1 na portu 9000.
  4. DOTNET_DiagnosticPorts=/foo/tool1.socket,nosuspend – (Linux a macOS) Tento příklad má nosuspend modifikátor. Modul runtime se pokusí připojit k rozhraní UNIX Domain Socket /foo/tool1.socket , které vytvoří externí nástroj. Další diagnostické porty by normálně způsobily pozastavení modulu runtime při spuštění čekání na příkaz resume, ale nosuspend způsobí, že modul runtime nečeká.

Úplná syntaxe portu je address[,(listen|connect)][,(suspend|nosuspend)]. connect je výchozí, pokud není zadána connect ani listen není zadána (a listen je podporována pouze modulem Runtime Mono v Androidu nebo iOSu). suspend je výchozí hodnota, pokud suspend není zadána nebo nosuspend není zadána.

Použití v diagnostických nástrojích dotnet

Nástroje, jako jsou dotnet-dump, dotnet-counters a dotnet-trace , všechny podpory collect nebo monitor příkazy, které komunikují s aplikací .NET přes diagnostický port.

  • Pokud tyto nástroje používají --processId argument, nástroj automaticky vypočítá výchozí adresu portu diagnostiky a připojí se k němu.
  • Při zadávání argumentu --diagnostic-port nástroj naslouchá na dané adrese a k konfiguraci připojení aplikace byste měli použít proměnnou DOTNET_DiagnosticPorts prostředí. Úplný příklad s čítači dotnet-counters najdete v tématu Použití diagnostického portu.

Použití ds-routeru k proxy portu diagnostiky

Všechny diagnostické nástroje dotnet-* očekávají připojení k diagnostickému portu, který je místní pojmenovaný kanál nebo unixový řadič domény. Mono často běží na izolovaném hardwaru nebo v emulátorech, které potřebují proxy přes protokol TCP, aby byly přístupné. Nástroj dotnet-dsrouter může proxy místní pojmenovaný kanál nebo unixový řadič domény tcp tak, aby se nástroje mohly použít v těchto prostředích. Další informace najdete v tématu dotnet-dsrouter.