SSD Nodes Learn 🎉 VPS od $5.50/mies.
Przewodniki Matt ConnorAutor: Matt Connor

Błąd unknown terminal type SSH jak naprawić

Problem wynika z braku wpisu w bazie terminfo na serwerze. Rozwiązanie polega na kompilacji własnego pliku w katalogu domowym bez potrzeby posiadania uprawnień roota.

Co oznacza błąd "unknown terminal type"

Błąd nieznanego typu terminala podczas połączenia SSH oznacza, że nazwa w TERM nie posiada odpowiadającego wpisu w bazie danych terminfo na serwerze. Twój emulator ustawia tę nazwę na laptopie. Baza danych, która musi ją rozpoznać, znajduje się na maszynie zdalnej. Gdy wyszukiwanie kończy się niepowodzeniem, każdy program korzystający z biblioteki curses na tym serwerze zatrzymuje się przed wyrenderowaniem czegokolwiek, ponieważ nie posiada opisu możliwości Twojego terminala.

Rozwiązanie, które zachowuje wszystkie funkcje Twojego emulatora, sprowadza się do jednego polecenia: skompilowania własnego wpisu terminfo do ~/.terminfo na serwerze. Biblioteka ncurses przeszukuje katalog domowy przed jakimkolwiek katalogiem systemowym, więc operacja ta nie wymaga uprawnień root i nie wprowadza zmian dla innych użytkowników.

TERM to nazwa, a terminfo to baza danych

TERM przechowuje jeden ciąg znaków, który jest kluczem. terminfo to skompilowana baza danych opisów terminali, a klucz służy programom do odnalezienia właściwego opisu. Opis zawiera informacje o liczbie obsługiwanych kolorów, sekwencjach bajtów przesuwających kursor do wiersza 12 i kolumny 40, kodach wysyłanych przez klawisz F5 oraz możliwości rysowania podkreśleń. Biblioteka ncurses, na której opiera się niemal każdy tekstowy interfejs użytkownika w systemie Linux, odczytuje ten opis podczas uruchamiania. Programy takie jak top, less, nano oraz watch nie są w stanie wyrenderować ekranu bez tych danych.

Sprawdź własny wpis:

echo "$TERM"
tput longname
infocmp -1 | head -20

tput longname wyświetla czytelny dla człowieka opis tego, co wskazuje TERM. Dla xterm-256color wynik wygląda następująco:

xterm with 256 colors

infocmp -1 dekompiluje cały wpis i wypisuje jedną funkcję w każdym wierszu. Jeśli oba polecenia działają, baza danych na tej maszynie rozpoznaje dany terminal. Taki sam stan jest wymagany po drugiej stronie połączenia SSH.

Dlaczego problem występuje tylko przez SSH

SSH przesyła wyłącznie nazwę, nic więcej. Gdy klient żąda pseudo-terminala, TERM jest przesyłane wraz z tym żądaniem. Dokumentacja OpenSSH jest jednoznaczna: "zmienna środowiskowa TERM jest zawsze przesyłana przy żądaniu pseudo-terminala, ponieważ jest wymagana przez protokół". Zatem powłoka logowania na VPS otrzymuje TERM=xterm-ghostty, xterm-kitty lub inną nazwę używaną przez emulator. Opis przypisany do tej nazwy pozostaje na laptopie, w lokalnej bazie danych. Serwer skonfigurowany przed powstaniem danego emulatora nie posiada informacji o tej nazwie. Nic w samym połączeniu SSH nie kopiuje opisów terminali i jest to działanie celowe: protokół przenosi nazwę, a nie zestaw możliwości.

Odtwórz błąd na własnej maszynie, używając nazwy, która z pewnością nie istnieje:

TERM=xterm-nosuchthing tput colors
echo "$?"
tput: unknown terminal "xterm-nosuchthing"

Kod wyjścia to 3, co w dokumentacji ncurses oznacza nieznany typ terminala lub brakującą bazę danych. Każdy program korzystający z curses wykonuje to samo wyszukiwanie, więc jedna brakująca nazwa generuje różne komunikaty w różnych programach, mimo że przyczyna jest wspólna. nano kończy działanie z Error opening terminal: xterm-nosuchthing., co jest standardowym błędem ncurses przy nieudanej próbie załadowania opisu podczas uruchamiania. vim wyświetla E558: Terminal entry not found in terminfo. less wyświetla WARNING: terminal is not fully functional. Pager, który działa częściowo, oraz edytor, który odmawia uruchomienia, wyglądają jak niezwiązane ze sobą błędy. W rzeczywistości chodzi o ten sam brakujący plik.

Gdzie ncurses szuka wpisu

Biblioteka ncurses przeszukuje lokalizacje w ustalonej kolejności, opisanej w terminfo(5):

  1. $TERMINFO, jeśli zmienna jest ustawiona. Przeszukiwany jest wyłącznie ten katalog.
  2. $HOME/.terminfo.
  3. każdy katalog wymieniony w $TERMINFO_DIRS.
  4. wkompilowane lokalizacje, które w systemach Debian i Ubuntu obejmują /etc/terminfo, /lib/terminfo oraz /usr/share/terminfo.

Uruchom infocmp -D na serwerze, aby wyświetlić listę używaną przez konkretną kompilację ncurses, zamiast polegać na powyższych ścieżkach. Krok 2 stanowi kluczowe rozwiązanie. Katalog domowy użytkownika jest przeszukiwany przed jakimkolwiek katalogiem systemowym, więc pojedynczy plik w ~/.terminfo naprawia wyszukiwanie dla danego konta bez konieczności instalacji pakietów i uprawnień root.

Poprawka 1: użyj terminala, który serwer już rozpoznaje

Najszybszym sposobem na odblokowanie połączenia jest wskazanie innej nazwy terminala dla bieżącej sesji:

TERM=xterm-256color ssh user@203.0.113.10

Aby ustawić to na stałe dla danego hosta, należy edytować plik ~/.ssh/config na komputerze lokalnym:

Host vps1
    HostName 203.0.113.10
    User deploy
    SetEnv TERM=xterm-256color

Opcja SetEnv wymaga klienta OpenSSH w wersji 7.8 lub nowszej, wydanej w sierpniu 2018 roku. TERM to jedyna zmienna, która nie wymaga zgody serwera: dokumentacja wskazuje, że w przeciwieństwie do SendEnv, serwer nie musi być przygotowany na przyjmowanie tej zmiennej środowiskowej. Dzięki temu rozwiązanie działa nawet w przypadku zabezpieczonego serwera sshd, który nie posiada żadnej dyrektywy AcceptEnv.

Koszt rozwiązania: utrata funkcji emulatora wykraczających poza standard xterm-256color. Dotyczy to między innymi kolorów 24-bitowych deklarowanych przez zdolność RGB oraz stylizowanych podkreśleń przez Smulx. Aplikacje nie wykryją tych możliwości, więc przełączą się na paletę 256 kolorów i standardowe podkreślenie. Ekran będzie działał poprawnie, jednak z mniejszą liczbą funkcji niż w przypadku wybranego terminala.

Nie należy rozwiązywać tego problemu poprzez dodanie export TERM=xterm-256color do pliku .bashrc na serwerze. Ten plik jest wykonywany przy każdym połączeniu, również dla terminali, które serwer poprawnie rozpoznaje, co spowoduje niepotrzebne ograniczenie sesji, które działały prawidłowo. Zmianę należy wprowadzić po stronie klienta, gdzie znany jest typ używanego emulatora.

Rozwiązanie 2: jednorazowe przesłanie wpisu terminfo na serwer

Jest to rozwiązanie, które pozwala zachować integralność emulatora. Należy zdekompilować wpis lokalnie, przesłać go przez SSH i skompilować po stronie zdalnej:

infocmp -x | ssh user@203.0.113.10 -- tic -x -

infocmp -x wypisuje wpis dla bieżącego TERM w formie tekstu źródłowego, uwzględniając rozszerzone (zdefiniowane przez użytkownika) możliwości. tic -x kompiluje ten kod źródłowy z powrotem do postaci binarnej na serwerze. Użycie -x po obu stronach jest istotne, ponieważ bez niego możliwości takie jak Smulx są tracone podczas przesyłu, co skutkuje wysłaniem ograniczonej kopii własnego terminala.

tic zapisuje plik w katalogu systemowym, jeśli posiada odpowiednie uprawnienia, a w przeciwnym razie korzysta z $HOME/.terminfo. Zwykłe konto na VPS uzyskuje dostęp do katalogu domowego, co jest pożądanym zachowaniem. Można również wskazać docelową ścieżkę:

infocmp -x | ssh user@203.0.113.10 -- tic -x -o '~/.terminfo' /dev/stdin

Cudzysłowy wokół ~/.terminfo nie są zbędne. ssh łączy słowa polecenia w jeden ciąg znaków i przekazuje go do zdalnej powłoki, podczas gdy nieobjęty cudzysłowem ~ zostałby rozwinięty przez lokalną powłokę. W takim przypadku wysłany zostałby dosłowny ciąg /home/yourname/.terminfo do maszyny, na której konto użytkownika może mieć inną nazwę. tic zakończy się błędem uprawnień lub zapisze plik w ścieżce, której ncurses nie przeszukuje. Użycie cudzysłowu sprawia, że tylda zostanie rozwinięta przez zdalną powłokę.

Zaloguj się i sprawdź:

ssh user@203.0.113.10
tput longname
ls -R ~/.terminfo

tput longname wypisujący opis terminala oznacza, że wyszukiwanie zakończyło się powodzeniem, a ls pokazuje skompilowany plik w podkatalogu nazwanym zgodnie z pierwszą literą nazwy terminala. Następnie uruchom top lub watch -n1 uptime, który odświeża ekran przy użyciu tej samej biblioteki, aby potwierdzić, że program korzystający z curses poprawnie renderuje obraz.

Koszty rozwiązania: jeden krok na serwer, a wpis znajduje się w katalogu domowym konkretnego konta na jednej maszynie. Po przebudowaniu VPS wpis zostanie usunięty. Warto dodać to polecenie do narzędzi używanych do automatyzacji konfiguracji i zarządzania wieloma serwerami, aby nowy host był od razu gotowy do pracy ze skompilowanym wpisem.

Poprawka 3: instalacja rozszerzonej bazy danych terminfo

Jeśli posiadasz uprawnienia root i chcesz, aby nazwa była rozpoznawana dla każdego konta w systemie:

sudo apt update
sudo apt install ncurses-term
tput -T xterm-ghostty longname

ncurses-term zawiera opisy terminali, których brakuje w instalacji podstawowej. Rozwiązuje to problem z nazwą dla użytkownika root oraz wszystkich pozostałych użytkowników, czego nie zapewnia poprawka 2.

Rozwiązanie to działa tylko wtedy, gdy wpis dla danego terminala istnieje w wydaniu ncurses dostarczonym przez dystrybucję, dlatego należy to sprawdzić, zamiast zakładać poprawność. Ubuntu 24.04 dostarcza ncurses-bin 6.4+20240113-1ubuntu2.1 (stan na sierpień 2026). Wpis dla Ghostty został dodany w ncurses 6.5-20241228, czyli w nowszej wersji, dlatego apt install ncurses-term w systemie Ubuntu 24.04 nie wygeneruje wpisu xterm-ghostty, niezależnie od liczby prób. tput -T <name> longname służy do weryfikacji: polecenie wyświetla opis, jeśli wpis istnieje, lub unknown terminal z kodem wyjścia 3, jeśli go brakuje.

Aby zainstalować pojedynczy wpis w całym systemie zamiast całego pakietu, skopiuj plik źródłowy i skompiluj go jako root:

infocmp -x | ssh user@203.0.113.10 -- 'cat > /tmp/term.src'
ssh -t user@203.0.113.10 -- sudo tic -x -o /usr/share/terminfo /tmp/term.src

Flaga -t w drugim poleceniu przydziela pseudo-terminal, dzięki czemu sudo może wyświetlić monit o hasło. Bez niej sudo może zakończyć działanie z błędem sudo: no tty present and no askpass program specified.

Pozwól emulatorowi wykonać transfer

Niektóre emulatory dostarczają narzędzia pomocnicze, które wykonują poprawkę 2 automatycznie. Program kitty posiada ssh kitten: kitten ssh myserver łączy się i kopiuje terminfo emulatora kitty na zdalny host. Dokumentacja tego narzędzia zawiera również metodę ręczną, infocmp -a xterm-kitty | ssh myserver tic -x -o \~/.terminfo /dev/stdin, z tyldą zabezpieczoną w sposób opisany powyżej. Ghostty dokumentuje infocmp -x xterm-ghostty | ssh YOUR-SERVER -- tic -x - i dostarcza integrację z powłoką (ssh-env oraz ssh-terminfo), a także akcję +ssh, które automatyzują obie poprawki.

Te narzędzia pomocnicze wykonują te same polecenia, które zostały wcześniej wprowadzone ręcznie. Znajomość metody ręcznej pozostaje istotna, ponieważ narzędzie pomocnicze nie może zadziałać, gdy połączenie inicjowane jest w innym miejscu, na przykład na serwerze przesiadkowym (jump host) lub wewnątrz skryptu.

Gdy błąd powraca

W ramach sudo -i. Powłoka logowania użytkownika root posiada HOME=/root, a sudo przechowuje Twoje TERM. ncurses przeszukuje teraz /root/.terminfo, który nie zawiera Twojego wpisu, dlatego błąd występuje wyłącznie dla konta root. Potwierdź to za pomocą sudo -i env i odczytaj linie HOME oraz TERM. Zainstaluj wpis w katalogu systemowym lub umieść kopię w /root/.terminfo.

Wewnątrz tmux lub screen. Programy te ustawiają własne TERM dla uruchomionych w nich procesów, zazwyczaj screen-256color lub tmux-256color. Starszy serwer rozpoznaje screen-256color i może nie znać tmux-256color, przez co powłoka zewnętrzna działa poprawnie, podczas gdy wszystko wewnątrz sesji kończy się niepowodzeniem. Przyczyna jest ta sama, zmienia się tylko nazwa. Uruchom tput -T tmux-256color longname na serwerze, aby sprawdzić, który z tych dwóch typów jest obsługiwany. Środowisko pracy terminalowej oparte na tmux maskuje ten problem do momentu połączenia się z hostem, który nie został jeszcze skonfigurowany.

Na nowym serwerze. ~/.terminfo jest przypisane do konta oraz maszyny, więc zreinstalowany VPS ponownie posiada pustą konfigurację.

Ekran wyświetla się, klawisze działają nieprawidłowo. Jeśli obraz jest poprawny, ale klawisze Home, End lub klawisze funkcyjne wstawiają przypadkowe znaki, oznacza to, że nazwa została przypisana do wpisu niezgodnego z używanym terminalem. Sekwencje klawiszy pochodzą z tego samego wpisu terminfo co możliwości renderowania, więc przybliżony wpis daje przybliżone działanie klawiszy. Jest to typowy rezultat zastosowania poprawki 1 na emulatorze, którego sekwencje klawiszy różnią się od xterm. Rozwiązaniem jest poprawka 2, ponieważ tylko właściwy wpis dla danego emulatora zawiera poprawne sekwencje.

FAQ

Dlaczego przez SSH widzę tylko komunikat "unknown terminal type"?

Ponieważ baza danych zawierająca definicję terminala musi znajdować się na serwerze. Emulator terminala instaluje swój opis na maszynie, na której jest uruchomiony, dzięki czemu lokalne programy znajdują go automatycznie. SSH przesyła jedynie wartość TERM, ponieważ protokół przenosi tę nazwę wraz z żądaniem pseudo-terminala. Zdalna biblioteka ncurses wyszukuje nazwę w zdalnej bazie danych i niczego nie znajduje, przez co initscr kończy się niepowodzeniem, a program zostaje zatrzymany.

Czy mogę to naprawić bez uprawnień root na serwerze?

Tak. Biblioteka ncurses przeszukuje $HOME/.terminfo przed jakimkolwiek katalogiem systemowym, więc wpis w tej lokalizacji wystarczy dla danego konta. Uruchom infocmp -x | ssh user@host -- tic -x - raz na serwerze. tic zapisuje dane w katalogu domowym, gdy nie ma uprawnień do zapisu w ścieżce systemowej, co jest typowe dla konta bez uprawnień administratora. Zaloguj się i uruchom tput longname, aby potwierdzić, że wyszukiwanie kończy się teraz powodzeniem.

Co tracę, ustawiając TERM=xterm-256color dla hosta?

Wszystkie możliwości, które opisuje emulator poza wpisem xterm-256color, takie jak obsługa 24-bitowych kolorów przez RGB oraz stylizowane podkreślenia przez Smulx. Programy nie widzą tych możliwości, więc korzystają z najbliższego dostępnego zamiennika. Sekwencje klawiszy funkcyjnych mogą również różnić się od tych w rzeczywistym terminalu. Umieść to ustawienie po stronie klienta w ~/.ssh/config, zamiast w .bashrc na serwerze, co spowodowałoby obniżenie jakości sesji dla terminali, które działały poprawnie.

Dlaczego błąd powraca po użyciu sudo -i?

sudo -i uruchamia powłokę logowania jako root z HOME=/root, zachowując jednocześnie wartość TERM. Biblioteka ncurses przeszukuje wtedy /root/.terminfo zamiast katalogu domowego użytkownika i niczego nie znajduje, więc root napotyka ten sam błąd, którego konto użytkownika już nie widzi. Uruchom sudo -i env i sprawdź linie HOME oraz TERM. Skompiluj wpis do katalogu systemowego za pomocą sudo tic -x -o /usr/share/terminfo lub skopiuj go do /root/.terminfo.

Czy apt install ncurses-term zawsze rozwiązuje problem?

Nie. Dodaje on tylko wpisy, które istniały w wydaniu ncurses dostarczonym przez dystrybucję. Ubuntu 24.04 zawiera ncurses 6.4 (ncurses-bin 6.4+20240113-1ubuntu2.1, stan na sierpień 2026), a wpis dla Ghostty został dodany w ncurses 6.5-20241228, więc pakiet ten nie może go zawierać. Sprawdź dostępność za pomocą tput -T <name> longname przed poleganiem na pakiecie i samodzielnie dostarcz wpis, jeśli sprawdzenie nadal zgłasza nieznany terminal.

#terminfo#ssh#ncurses#tput#terminal