Udostępnij przez


Porty diagnostyczne

Ten artykuł dotyczy: ✔️ .NET Core 3.1 i nowszych wersji

Środowisko uruchomieniowe platformy .NET uwidacznia punkt końcowy usługi, który umożliwia innym procesom wysyłanie poleceń diagnostycznych i odbieranie odpowiedzi za pośrednictwem kanału IPC. Ten punkt końcowy jest nazywany portem diagnostycznym. Polecenia można wysyłać do portu diagnostycznego do:

  • Przechwyć zrzut pamięci.
  • Uruchom ślad EventPipe.
  • Zażądaj wiersza polecenia użytego do uruchomienia aplikacji.

Port diagnostyczny obsługuje różne transporty w zależności od platformy. Obecnie implementacje środowiska uruchomieniowego CoreCLR i Mono używają nazwanych potoków w systemach Windows oraz gniazd domeny Unix w systemach Linux i macOS. Implementacja środowiska uruchomieniowego Mono w systemach Android, iOS i tvOS używa protokołu TCP/IP. Kanał używa niestandardowego protokołu binarnego. Większość deweloperów nigdy nie będzie bezpośrednio korzystać z bazowego kanału i protokołu, ale raczej będzie używać graficznego interfejsu użytkownika lub narzędzi interfejsu wiersza polecenia, które komunikują się w ich imieniu. Na przykład narzędzia dotnet-dump i dotnet-trace abstrahują wysyłanie poleceń protokołu w celu przechwytywania zrzutów i rozpoczynania śladów. W przypadku programistów, którzy chcą pisać niestandardowe narzędzia, pakiet NuGet Microsoft.Diagnostics.NETCore.Client zapewnia abstrakcję API platformy .NET dla podstawowego transportu i protokołu.

Zagadnienia dotyczące zabezpieczeń

Port diagnostyczny uwidacznia poufne informacje o uruchomionej aplikacji. Jeśli niezaufany użytkownik uzyska dostęp do tego kanału, może obserwować szczegółowy stan programu, w tym wszelkie wpisy tajne w pamięci i dowolnie modyfikować wykonywanie programu. W środowisku uruchomieniowym CoreCLR domyślny port diagnostyczny jest skonfigurowany tak, aby był dostępny tylko przez to samo konto użytkownika, które uruchomiło aplikację lub przez konto z uprawnieniami administratora. Jeśli model zabezpieczeń nie ufa innym procesom z tymi samymi poświadczeniami konta użytkownika, możesz wyłączyć wszystkie porty diagnostyczne, ustawiając zmienną środowiskową DOTNET_EnableDiagnostics=0. To ustawienie zablokuje możliwość korzystania z narzędzi zewnętrznych, takich jak debugowanie platformy .NET lub dowolne z narzędzi diagnostycznych dotnet-*.

Domyślny port diagnostyczny

W systemach Windows, Linux i macOS środowisko uruchomieniowe ma domyślnie otwarty jeden port diagnostyczny w dobrze znanym punkcie końcowym. Jest to port, z którego narzędzia diagnostyczne dotnet-* łączą się automatycznie, gdy nie zostały jawnie skonfigurowane do korzystania z alternatywnego portu. Punkt końcowy to:

  • Windows — Nazwany Potok \\.\pipe\dotnet-diagnostic-{pid}
  • Linux i macOS — gniazdo domeny systemu Unix {temp}/dotnet-diagnostic-{pid}-{disambiguation_key}-socket

{pid} jest identyfikatorem procesu zapisanym w dziesiętnym, {temp} jest zmienną TMPDIR środowiskową lub wartością /tmp , jeśli TMPDIR jest niezdefiniowana/pusta, i {disambiguation_key} jest czasem rozpoczęcia procesu zapisanym w przecinku. W systemach macOS i NetBSD czas rozpoczęcia procesu to liczba sekund od czasu epoki systemu UNIX. Na wszystkich innych platformach jest to jiffies od czasu uruchomienia systemu.

Wstrzymaj środowisko uruchomieniowe podczas uruchamiania

Domyślnie środowisko uruchomieniowe wykonuje kod zarządzany natychmiast po uruchomieniu, niezależnie od tego, czy jakiekolwiek narzędzia diagnostyczne nawiązały połączenie z portem diagnostycznym. Czasami warto poczekać na uruchomienie kodu zarządzanego przez środowisko uruchomieniowe do momentu połączenia narzędzia diagnostycznego w celu obserwowania początkowego zachowania programu. Ustawienie zmiennej środowiskowej DOTNET_DefaultDiagnosticPortSuspend=1 powoduje, że środowisko uruchomieniowe czeka, aż narzędzie połączy się z domyślnym portem. Jeśli żadne narzędzie nie jest dołączone po kilku sekundach, środowisko uruchomieniowe wyświetli komunikat ostrzegawczy do konsoli z informacją, że nadal czeka na dołączenie narzędzia.

Konfigurowanie dodatkowych portów diagnostycznych

Uwaga / Notatka

Działa to tylko w przypadku aplikacji z programem .NET 5 lub nowszym.

Środowiska uruchomieniowe Mono i CoreCLR mogą używać niestandardowych skonfigurowanych portów diagnostycznych w connect roli. Mono obsługuje również niestandardowe porty TCP/IP w roli listen, gdy są używane z dotnet-dsrouter na Androidzie lub iOS. Te porty niestandardowe są dodatkiem do portu domyślnego, który pozostaje dostępny. Istnieje kilka typowych powodów, dla których przydatne są porty niestandardowe:

  • W systemach Android, iOS i tvOS nie ma portu domyślnego, dlatego skonfigurowanie portu jest niezbędne do korzystania z narzędzi diagnostycznych.
  • W środowiskach z kontenerami lub zaporami możesz skonfigurować przewidywalny adres punktu końcowego, który nie różni się w zależności od identyfikatora procesu, jak port domyślny. Następnie można jawnie dodać port niestandardowy do listy dozwolonych lub przekierować go przez niektóre granice zabezpieczeń.
  • W przypadku narzędzi do monitorowania przydatne jest, aby narzędzie nasłuchiwało na punkcie końcowym, a runtime aktywnie próbował nawiązać z nim połączenie. Pozwala to uniknąć konieczności ciągłego korzystania z narzędzia do monitorowania w celu sondowania nowych uruchamianych aplikacji. W środowiskach, w których domyślny port diagnostyczny jest niedostępny, należy również unikać konfigurowania monitora z niestandardowym punktem końcowym dla każdej monitorowanej aplikacji.

W każdym kanale komunikacyjnym między narzędziem diagnostycznym a środowiskiem uruchomieniowym platformy .NET jedna strona musi być odbiornikiem i poczekać na nawiązanie połączenia po drugiej stronie. Środowisko uruchomieniowe można skonfigurować do działania w connect roli dla dowolnego portu. (Środowisko uruchomieniowe Mono można również skonfigurować do działania w listen roli dla dowolnego portu). Porty można również niezależnie skonfigurować do wstrzymania podczas uruchamiania, czekając na uruchomienie narzędzia diagnostycznego w celu wydania polecenia wznawiania. Porty skonfigurowane do nawiązywania połączenia powtarzają próby połączenia przez czas nieokreślony, jeśli zdalny punkt końcowy nie nasłuchuje lub jeśli połączenie zostanie utracone. Jednak aplikacja nie zawiesza automatycznie kodu zarządzanego podczas oczekiwania na nawiązanie tego połączenia. Jeśli chcesz, aby aplikacja czekała na nawiązanie połączenia, użyj opcji wstrzymania podczas uruchamiania.

Porty niestandardowe są konfigurowane przy użyciu zmiennej środowiskowej DOTNET_DiagnosticPorts . Ta zmienna powinna być ustawiona na rozdzielaną średnikami listę opisów portów. Każdy opis portu składa się z adresu punktu końcowego i opcjonalnych modyfikatorów, które kontrolują rolę connect lub listen środowiska uruchomieniowego oraz czy środowisko uruchomieniowe powinno zostać zawieszone podczas uruchamiania. W systemie Windows adres punktu końcowego jest nazwą nazwanego potoku bez prefiksu \\.\pipe\ . W systemach Linux i macOS jest to pełna ścieżka do gniazda domeny systemu Unix. W systemach Android, iOS i tvOS adres jest adresem IP i portem. Przykład:

  1. DOTNET_DiagnosticPorts=my_diag_port1 - (Windows) Środowisko uruchomieniowe łączy się z nazwanym potokiem \\.\pipe\my_diag_port1.
  2. DOTNET_DiagnosticPorts=/foo/tool1.socket;foo/tool2.socket - (Linux i macOS) Środowisko uruchomieniowe łączy się zarówno z gniazdami /foo/tool1.socket domeny systemu Unix, jak i /foo/tool2.socket.
  3. DOTNET_DiagnosticPorts=127.0.0.1:9000 - (Android, iOS i tvOS) Środowisko uruchomieniowe nawiązuje połączenie z adresem IP 127.0.0.1 na porcie 9000.
  4. DOTNET_DiagnosticPorts=/foo/tool1.socket,nosuspend — (Linux i macOS) Ten przykład zawiera nosuspend modyfikator. Środowisko uruchomieniowe próbuje nawiązać połączenie z gniazdem /foo/tool1.socket domeny systemu Unix utworzonym przez narzędzie zewnętrzne. Dodatkowe porty diagnostyczne zwykle powodują, że środowisko uruchomieniowe zawiesza się podczas uruchamiania, oczekując na polecenie wznowienia, ale nosuspend powoduje, że środowisko uruchomieniowe nie czeka.

Pełną składnią portu jest address[,(listen|connect)][,(suspend|nosuspend)]. connect jest wartością domyślną, jeśli nie określono ani connect, ani listen (i listen jest obsługiwana tylko przez środowisko uruchomieniowe Mono w systemie Android lub iOS). suspend jest wartością domyślną, jeśli ani suspend, ani nosuspend nie są określone.

Użycie w narzędziach diagnostycznych dotnet

Narzędzia, takie jak dotnet-dump, dotnet-counters i dotnet-trace, obsługują collect lub monitor polecenia komunikujące się z aplikacją .NET przez port diagnostyczny.

  • Gdy te narzędzia używają argumentu --processId , narzędzie automatycznie oblicza domyślny adres portu diagnostycznego i nawiązuje z nim połączenie.
  • Podczas określania argumentu --diagnostic-port narzędzie nasłuchuje na danym adresie i należy użyć zmiennej środowiskowej DOTNET_DiagnosticPorts do skonfigurowania aplikacji w celu nawiązania połączenia. Aby uzyskać pełny przykład z użyciem narzędzia dotnet-counters, zobacz Korzystanie z portu diagnostycznego (Using the Diagnostic Port).

Użyj ds-router do proxy portu diagnostycznego

Wszystkie narzędzia diagnostyczne dotnet-* oczekują połączenia z portem diagnostycznym, który jest lokalnym nazwanym potokiem lub gniazdem domeny systemu Unix. Mono często działa na izolowanym sprzęcie lub w emulatorach, które wymagają serwera proxy za pośrednictwem protokołu TCP, aby umożliwić dostęp. Narzędzie dotnet-dsrouter może przekierowywać lokalne nazwane potoki lub gniazda domeny systemu Unix do protokołu TCP, co umożliwia używanie narzędzi w tych środowiskach. Aby uzyskać więcej informacji, zobacz dotnet-dsrouter.