Błąd „command not found: dotnet” jest jednym z najczęściej spotykanych problemów w pracy z platformą .NET na systemach Unix-like, przede wszystkim na Linuxie i macOS. Wynika on z braku możliwości odnalezienia pliku wykonywalnego dotnet w katalogach zdefiniowanych w zmiennej środowiskowej PATH. Przyczyny sięgają od nieprawidłowej instalacji i błędów konfiguracji, po problemy z menedżerami pakietów i architekturą systemu. Dotyczy to zarówno użytkowników bash, jak i zsh, a każda z tych powłok może wymagać nieco innej procedury naprawczej.
Podstawowe mechanizmy i przyczyny błędu
Jak działa wyszukiwanie poleceń w systemach Unix?
Powłoki, takie jak bash oraz zsh, szukają plików wykonywalnych w katalogach podanych w PATH. Jeśli plik o nazwie dotnet nie zostanie znaleziony, pojawia się komunikat „command not found”.
Lokalizacja instalacji .NET może się różnić w zależności od systemu:
- w systemach Linux często /usr/share/dotnet/dotnet, /usr/local/share/dotnet/dotnet lub /usr/bin/dotnet,
- w systemie macOS typowo /usr/local/share/dotnet/dotnet lub /usr/local/share/dotnet/x64/dotnet.
Różnice te często prowadzą do problemów z dostępnością polecenia dotnet w PATH.
Instalacje systemowe a użytkownika
Sposób instalacji .NET także wpływa na występowanie błędów:
- instalacje systemowe przez administratora zwykle konfigurują prawidłowe dowiązania symboliczne i lokalizacje,
- instalacje wykonywane przez użytkownika (np. przez Snap lub skrypty) mogą umieszczać pliki .NET w katalogach domowych lub niestandardowych, których nie ma domyślnie w PATH.
Dodatkowo, obecność wielu wersji .NET komplikuje sytuację i wymaga dokładnej konfiguracji środowiska.
Problemy na macOS
Apple Silicon i Intel
Implementacja Apple Silicon (M1, M2) wprowadza dodatkowe niuanse:
- Intel: instalacja w /usr/local/share/dotnet/,
- Apple Silicon: instalacja w /usr/local/share/dotnet/x64/ dla wersji x64 lub w katalogu dla ARM64.
Dowiązanie symboliczne do /usr/local/bin/ jest kluczowe do prawidłowego działania – jego brak lub uszkodzenie skutkuje błędem.
System Integrity Protection (SIP) może blokować modyfikację systemowych katalogów. W takim przypadku należy użyć alternatywnych lokalizacji lub dostosować uprawnienia.
Problemy powłoki zsh na macOS
Domyślna powłoka zsh obsługuje zmienne środowiskowe nieco inaczej niż bash:
- zmienne typu $HOME mogą nie być prawidłowo rozszerzane, jeśli używane są w konfiguracji PATH,
- zalecane jest podanie pełnej ścieżki np. /Users/nazwa_użytkownika/.dotnet/tools zamiast $HOME/.dotnet/tools.
Edytując odpowiedni plik (/private/etc/paths.d/dotnet-cli-tools lub ~/.zshrc) należy stosować pełne ścieżki.
Problemy dystrybucji Linux
Ubuntu i pochodne
Do najczęstszych problemów należy brak pliku /etc/dotnet/install_location po instalacji z pakietów .deb:
- runtime nie może zostać wykryty przez aplikacje AppHost,
- SDK potrafi być dostępne w PATH, ale uruchamianie aplikacji się nie udaje,
- możliwe rozwiązanie: ręczne przeniesienie plików install_location do /etc/dotnet/.
Fedora i RPM
Instalacje RPM mogą nie tworzyć symlinka /usr/bin/dotnet:
- niezbędne jest ręczne utworzenie dowiązania symbolicznego,
- reinstalacja pakietu dotnet-host może pomóc w razie jego braku lub uszkodzenia,
- podczas aktualizacji mogą zniknąć stare symlinki.
Arch Linux i rolling release
Rolling release i częste aktualizacje to:
- ryzyko konfliktów przy instalacji kilku wersji metodami hybrydowymi,
- zalecane jest regularne czyszczenie i spójne zarządzanie lokalizacjami.
Zmienna środowiskowa DOTNET_ROOT i PATH
Konfiguracja DOTNET_ROOT
DOTNET_ROOT wskazuje katalog instalacji runtime i SDK .NET:
- nieustawione lub błędnie ustawione może blokować uruchamianie aplikacji,
- należy wskazać dokładną lokalizację oraz dodać ją do PATH.
Niepoprawna wartość DOTNET_ROOT może przesłonić systemową instalację .NET i blokować start aplikacji.
Utrwalanie zmian PATH
Aby zmiany były trwałe, należy konfigurować PATH w odpowiednich plikach profilu:
- bash: ~/.bash_profile, ~/.bashrc,
- zsh: ~/.zshrc, ~/.zprofile,
- Korn shell: ~/.kshrc, ~/.profile.
Uwaga! Niektóre aplikacje wymagają restartu terminala lub systemu, by rozpoznać nowe zmienne środowiskowe.
Problemy z pakietami Snap
Instalacja przez Snap może prowadzić do:
- izolowania środowiska,
- dostępność pliku pod nazwą dotnet-sdk.dotnet zamiast dotnet,
- ograniczonej współpracy z narzędziami i IDE (np. dotnet watch),
- potrzeby instalacji w trybie classic lub utworzenia aliasów/dowiązań symbolicznych.
Dla pełnej funkcjonalności w środowisku deweloperskim zalecana jest klasyczna instalacja .NET.
Problemy integracji z IDE
IDE, w szczególności Visual Studio Code i motor OmniSharp, mogą mieć problem z detekcją SDK zainstalowanego przez Snap:
- dotnet –info może zwracać błąd SIGABRT uruchamiane z poziomu GUI,
- rekomendowane jest modyfikowanie PATH tak, by ścieżka do SDK Snap znajdowała się przed /snap/bin,
- opcjonalnie można utworzyć dowiązanie symboliczne w /usr/local/bin/.
Metody diagnostyczne i naprawcze
Narzędzia weryfikujące stan systemu
Do weryfikacji instalacji i konfiguracji użyj poleceń:
which dotnet– sprawdza, czy plik można znaleźć przez PATH,whereis dotnet– lokalizuje pliki powiązane z .NET,echo $PATHorazecho $DOTNET_ROOT– sprawdzają bieżące ustawienia środowiskowe.
Sprawdzenie tych komend pozwoli szybko uszczegółowić przyczynę niedostępności polecenia dotnet.
Weryfikacja i naprawa instalacji .NET
Podstawowe narzędzia diagnostyczne .NET:
dotnet --info– wylistuje dostępne SDK i runtime,dotnet --list-sdksidotnet --list-runtimes– wymieniają dostępne wersje,- weryfikacja pliku /etc/dotnet/install_location (na Linuxie) – poprawne AppHost.
Tworzenie dowiązań symbolicznych
Ręczne tworzenie symlinków to jedno z najskuteczniejszych rozwiązań:
-
sudo ln -s /usr/local/share/dotnet/dotnet /usr/local/bin/dotnet– macOS (Intel), -
sudo ln -s /usr/local/share/dotnet/x64/dotnet /usr/local/bin/dotnet– macOS (Apple Silicon, x64), -
sudo ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet– Linux.
Najpierw sprawdź, czy dowiązanie nie jest uszkodzone:
-
ls -la /usr/local/bin/dotnet -
rm /usr/local/bin/dotnet– usuń niesprawne dowiązanie.
Nieprawidłowe źródło symlinka spowoduje niesprawne polecenie dotnet!
Platformowe rozwiązania problemu
macOS
Dla macOS rekomendowane kroki:
- sprawdź obecność katalogu /usr/local/share/dotnet/,
- jeśli brak, zainstaluj .NET z oficjalnej strony,
- stwórz dowiązanie symboliczne do /usr/local/bin/dotnet,
- w przypadku zsh dodaj ścieżkę w ~/.zshrc:
export PATH="/usr/local/share/dotnet:$PATH",
potemsource ~/.zshrc.
Ubuntu/Debian
Zalecana procedura instalacji z oficjalnego repozytorium Microsoft:
- dodaj klucz oraz źródło repozytorium (
wget .... ; sudo dpkg -i ....), sudo apt update && sudo apt install dotnet-sdk-8.0,- jeśli runtime nie działa – przenieś install_location:
sudo mv /usr/lib/dotnet/install_location /etc/dotnet/install_location.
Fedora/CentOS
Postępowanie wygląda następująco:
sudo dnf install dotnet-sdk-8.0lubsudo yum install dotnet-sdk-8.0,- jeśli dotnet nie działa, wykonaj:
sudo ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet, sudo dnf reinstall dotnet-host– w razie problemów z symlinkiem.
Instalacja binarna .NET: alternatywa
Jak przeprowadzić instalację binarną?
Alternatywą dla menedżerów pakietów jest instalacja binarna:
- pobierz archiwum tar.gz:
curl -Lo dotnet.tar.gz ..., - utwórz katalog docelowy i rozpakuj:
mkdir ~/dotnet && tar -C ~/dotnet -xf dotnet.tar.gz, - ustaw
export DOTNET_ROOT=~/dotnetiexport PATH=$PATH:~/dotnetw plikach konfiguracyjnych powłoki.
Zmienna DOTNET_ROOT musi być poprawnie ustawiona – od niej zależy prawidłowe działanie aplikacji.
Zarządzanie wersjami i aktualizacjami
Korzyść z instalacji binarnej to łatwe zarządzanie wieloma wersjami:
- każda wersja w osobnym katalogu np. ~/dotnet-8.0, ~/dotnet-9.0,
- przełączanie wersji przez zmianę DOTNET_ROOT,
- ręczna aktualizacja polega na pobraniu i rozpakowaniu nowego archiwum, a zalecane jest wykonywanie kopii zapasowych przed podmianą.
Najlepsze praktyki: prewencja i utrzymanie
Standardowa, polecana ścieżka instalacji
Microsoft zaleca korzystanie tylko z oficjalnych repozytoriów oraz instalatorów .NET. Dzięki temu:
- instalacja przebiega automatycznie i poprawnie ustawia wszystkie ścieżki,
- konfiguracja środowiskowa jest mniej podatna na błędy,
- ograniczasz ryzyko konfliktu kilku instalacji.
Monitorowanie i testowanie po aktualizacjach
Kluczowa jest kontrola po każdej aktualizacji systemu:
- wykonaj test
dotnet --infoorazdotnet --list-sdks, - uruchom
dotnet new consolew katalogu testowym, - prowadź dziennik zmian i operacji na środowisku .NET.
Kopia zapasowa i odtwarzanie konfiguracji
Aby szybko reagować w razie awarii:
- regularnie twórz kopie plików ~/.bashrc, ~/.zshrc, ~/.profile i /etc/environment,
- w środowiskach zespołowych użyj GIT lub innych VCS,
- sprawdzaj poprawność dowiązań symbolicznych oraz uprawnień plików.
Narzędzia diagnostyczne i zarządzanie środowiskiem .NET
Zaawansowane narzędzia diagnostyczne
W razie większych problemów sięgnij po:
env | grep -i dotnet– sprawdza globalne ustawienia środowiskowe,alias– weryfikuje, czy dotnet nie zostało zastąpione aliasem,strace -e trace=execve bash -c "dotnet --info"– śledzi próby uruchomienia polecenia,journalctl | grep dotnetidmesg | grep dotnet– analizują logi systemowe.
Narzędzia pokroju dotnet-install.sh lub dotnet-version-manager automatyzują instalację i przełączanie wersji .NET. Docker eliminuje potrzebę ręcznej konfiguracji środowiska, oferując gotowe obrazy Microsoft .NET.
Integracja z IDE i problematyka narzędzi .NET
Visual Studio Code i OmniSharp
Problemy z rozpoznawaniem SDK przez OmniSharp rozwiązuj przez:
- ustawienie „omnisharp.dotnetPath” w settings.json (np.
"omnisharp.dotnetPath": "/usr/local/bin/dotnet"), - uruchamianie VS Code z terminala dla zachowania spójnego środowiska.
JetBrains Rider i inne IDE
Rider pozwala ręcznie wskazać ścieżkę do SDK w ustawieniach. W przypadku innych edytorów również warto zadbać o odpowiednią konfigurację DOTNET_ROOT, PATH oraz o włączanie tych ścieżek dla procesów uruchamianych z GUI.
Problemy z narzędziami globalnymi i lokalnymi .NET
Globalne narzędzia
Globalne narzędzia .NET (dotnet tool install -g …):
- są instalowane domyślnie w ~/.dotnet/tools,
- wymagają dodania tego katalogu do PATH w pliku profilu powłoki,
- sprawdź uprawnienia do katalogu, zwłaszcza w przypadku błędów „permission denied”.
dotnet tool list -g daje listę zainstalowanych globalnych narzędzi wraz z ich lokalizacjami.
Narzędzia lokalne (project-specific)
Obsługa narzędzi lokalnych wymaga:
- obecność pliku dotnet-tools.json w repozytorium,
- odtworzenie narzędzi przez
dotnet tool restore, - w środowisku zespołowym kontrola wersji pliku dotnet-tools.json jest kluczowa,
- sprawdzaj instalacje i uprawnienia w .config/dotnet-tools projektu.
Zagadnienia bezpieczeństwa i uprawnień
SIP na macOS i alternatywne lokalizacje dowiązań
SIP może blokować modyfikacje w /usr/local/bin. Wtedy:
- stwórz ~/bin i dodaj do PATH (
export PATH=~/bin:$PATH), - zainstaluj Xcode Command Line Tools przez
xcode-select --install, jeśli jest wymagana kompilacja natywna.
Uprawnienia na Linuxie
Sprawdzaj i naprawiaj uprawnienia:
ls -la /usr/bin/dotnet– weryfikacja,chmod +x /usr/bin/dotnet,chmod 755 /usr/bin/dotnet– nadanie uprawnień,- kontrola polityk SELinux, AppArmor w razie komunikatów o blokowaniu aplikacji.
Testowanie rozwiązania
Podstawowe testy działania .NET
Po naprawieniu środowiska .NET należy wykonać testy:
dotnet --info– sprawdź dostępność SDK i runtime,dotnet new console -n TestProjectidotnet build– test kompilacji projektu,dotnet run– uruchom testową aplikację,- sprawdź instalację narzędzi globalnych
dotnet tool install -g dotnet-ef.
Testy w różnych kontekstach użytkowania
- odpal dotnet z różnych kont użytkowników,
- sprawdź środowisko po restarcie systemu,
- uruchom z IDE z poziomu GUI i terminala.
Pełna weryfikacja pozwoli mieć pewność, że środowisko .NET jest dostępne i działa poprawnie niezależnie od sposobu użycia.
Dokumentacja i utrzymywanie środowiska
- spisuj wykonane kroki diagnostyczne i naprawcze,
- regularnie testuj środowisko po aktualizacjach,
- prowadź log problemów i ich rozwiązań.
Prawidłowa dokumentacja oraz przemyślany proces utrzymania środowiska znacznie uproszczą rozwiązywanie podobnych problemów w przyszłości.