SSD Nodes Learn 🎉 VPS від $5.50/міс
Посібники Matt ConnorВід Matt Connor

Як виправити «unknown terminal type» через SSH

Помилка «unknown terminal type» означає, що сервер не має запису terminfo для TERM. Додайте його до ~/.terminfo без root і збережіть можливості термінала.

Що означає «невідомий тип термінала»

Помилка невідомого типу термінала через SSH означає, що для назви в TERM немає відповідного запису в базі даних terminfo на сервері. Ваш емулятор встановлює цю назву на ноутбуці. База даних, яка має її розпізнати, розташована на віддаленій машині. Якщо пошук не знаходить запис, кожна програма curses на цьому сервері завершує роботу ще до виведення будь-яких даних, оскільки не має опису можливостей вашого термінала.

Щоб зберегти всі можливості емулятора, виконайте одну команду: скомпілюйте власний запис terminfo у ~/.terminfo на сервері. ncurses шукає записи у вашому домашньому каталозі раніше, ніж у системних каталогах, тому root не потрібен і налаштування інших користувачів не зміняться.

TERM — це назва, а terminfo — база даних

TERM містить один рядок, і цей рядок є лише ключем. terminfo — це скомпільована база описів терміналів, а ключ потрібен програмі, щоб знайти правильний опис. В описі зазначено, скільки кольорів підтримує термінал, які байти переміщують курсор у рядок 12, стовпець 40, які байти надсилає клавіша F5 і чи може термінал виводити підкреслення зі стилізацією. ncurses — бібліотека, на якій побудовано майже кожен текстовий інтерфейс користувача в Linux, — зчитує цей опис під час запуску. Програми на кшталт top, less, nano і watch не можуть відобразити навіть один екран без нього.

Перевірте власний запис:

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

tput longname виводить зрозумілий для людини опис того, що називає TERM. Для xterm-256color команда виводить:

xterm with 256 colors

infocmp -1 декомпілює весь запис і виводить одну можливість у кожному рядку. Якщо обидві команди виконуються успішно, база даних на цій машині знає цей термінал. Такий самий стан потрібен і на іншому боці SSH-з’єднання.

Чому це ламається лише через SSH

SSH надсилає ім’я і більше нічого. Коли клієнт запитує псевдотермінал, разом із цим запитом передається TERM. У посібнику OpenSSH це сформульовано однозначно: «змінна середовища TERM завжди надсилається, коли запитується псевдотермінал, оскільки цього вимагає протокол». Отже, ваша login shell на VPS отримує TERM=xterm-ghostty, або xterm-kitty, або інше ім’я, яке використовує ваш емулятор. Опис цього імені залишається на вашому ноутбуці, у його базі даних. Сервер, створений до появи вашого емулятора, ніколи не чув про це ім’я. Ніщо в самому SSH-з’єднанні не копіює описи терміналів, і це зроблено навмисно: протокол передає ім’я, а не набір можливостей.

Відтворіть помилку на власній машині, використавши ім’я, якого точно не існує:

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

Код завершення — 3. У документації ncurses це описано як невідомий тип термінала або відсутню базу даних. Кожна curses-програма виконує той самий пошук, тому одне відсутнє ім’я спричиняє різні повідомлення в різних програмах, хоча причина в усіх одна. nano завершується з повідомленням Error opening terminal: xterm-nosuchthing. — стандартною помилкою ncurses, яка виникає, коли опис не вдається завантажити під час запуску. vim виводить E558: Terminal entry not found in terminfo. less виводить WARNING: terminal is not fully functional. Пейджер, який працює лише частково, і редактор, що відмовляється запускатися, можуть виглядати як не пов’язані між собою помилки. Насправді причина одна: відсутній файл.

Де ncurses шукає запис

ncurses шукає записи у фіксованому порядку, описаному в terminfo(5):

  1. $TERMINFO, якщо цю змінну встановлено. Пошук виконується лише в цьому каталозі.
  2. $HOME/.terminfo.
  3. У кожному каталозі, переліченому в $TERMINFO_DIRS.
  4. У каталогах, вбудованих під час компіляції. У Debian та Ubuntu це, зокрема, /etc/terminfo, /lib/terminfo і /usr/share/terminfo.

Виконайте на сервері infocmp -D, щоб вивести список, який використовує саме його збірка ncurses, а не покладайтеся на наведені вище шляхи. Уся суть полягає в кроці 2. Ваш домашній каталог перевіряється раніше за будь-який системний каталог, тому один файл у ~/.terminfo виправляє пошук для вашого облікового запису без інсталяції пакета та без root.

Виправлення 1: використайте TERM, який уже відомий серверу

Найшвидше розблокувати підключення можна, вказавши інший термінал для одного сеансу:

TERM=xterm-256color ssh user@203.0.113.10

Щоб застосувати це постійно для цього хоста, додайте налаштування у ~/.ssh/config на своєму ноутбуці:

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

Для SetEnv на клієнті потрібен OpenSSH 7.8 або новіший, випущений у серпні 2018 року. TERM — єдина змінна, для якої не потрібен дозвіл сервера: у документації зазначено: «Так само як і для SendEnv, за винятком змінної TERM, сервер має бути підготовлений до приймання змінної середовища». Тому це працює навіть із посилено захищеним sshd, у конфігурації якого взагалі немає рядка AcceptEnv.

Недолік полягає у втраті всіх можливостей, які ваш емулятор описує понад звичайний xterm-256color. Сюди входить 24-бітний колір, оголошений через можливість RGB, і стилізоване підкреслення через Smulx. Програми більше не бачать цих можливостей, тому переходять на 256 кольорів і звичайне підкреслення. Екран працює. Просто він має менше можливостей, ніж вибраний вами термінал.

Не намагайтеся виправити це, додавши export TERM=xterm-256color до .bashrc на сервері. Цей файл обробляється для кожного підключення, зокрема для підключень із терміналів, назви яких сервер знає. Тому він погіршить сеанси, які й без цього працювали правильно. Зберігайте це перевизначення на клієнті, де ви знаєте, який емулятор використовуєте.

Виправлення 2: один раз передайте запис terminfo на сервер

Це виправлення зберігає ваш емулятор без змін. Локально декомпілюйте запис, передайте його через SSH і скомпілюйте на віддаленому сервері:

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

infocmp -x виводить запис для поточного TERM як вихідний текст, включно з розширеними (визначеними користувачем) можливостями. tic -x компілює цей вихідний текст назад у двійковий опис на сервері. -x з обох боків має значення, оскільки без нього такі можливості, як Smulx, втрачаються під час передавання, і на сервер потрапляє урізана копія вашого термінала.

tic записує дані в системний каталог, якщо це можливо, а якщо користувач не має туди доступу на запис, використовує $HOME/.terminfo. Звичайний обліковий запис на VPS отримує домашній каталог, і саме це вам потрібно. Ви також можете явно вказати каталог призначення:

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

Лапки навколо ~/.terminfo потрібні не для оформлення. ssh об’єднує слова команди в один рядок і передає його віддаленій оболонці, тому оболонка на локальній машині спочатку розгортає ~ без лапок. У результаті ви передаєте буквальний /home/yourname/.terminfo на машину, де ваш обліковий запис може мати іншу назву. tic завершується помилкою доступу або записує дані в каталог, який ncurses ніколи не перевіряє. Візьміть тильду в лапки, і її розгорне віддалена оболонка.

Увійдіть на сервер і перевірте:

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

Виведення tput longname опису вашого термінала означає, що пошук тепер успішний, а ls показує скомпільований файл у підкаталозі, названому першою літерою назви термінала. Потім виконайте top або watch -n1 uptime, яка перемальовує екран через ту саму бібліотеку, щоб переконатися, що реальна програма curses коректно виводить дані на екран.

Ціна цього підходу: один крок для кожного сервера, а запис зберігається в домашньому каталозі одного облікового запису на одній машині. Після відновлення VPS він зникне. Додайте команду до засобу, який ви використовуєте для підготовки та одночасного керування кількома серверами, щоб новий хост одразу отримував скомпільований запис.

Виправлення 3: інсталюйте розширену базу даних terminfo

Якщо у вас є root і потрібно, щоб ім’я розпізнавалося для кожного облікового запису на сервері:

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

ncurses-term містить описи терміналів, яких немає в базовій інсталяції. Це виправляє проблему для root і всіх інших користувачів, на відміну від виправлення 2.

Це допомагає лише тоді, коли запис вашого термінала є у версії ncurses, яку містить пакет вашого дистрибутива. Тому перевірте його наявність, а не робіть припущень. Ubuntu 24.04 постачається з ncurses-bin 6.4+20240113-1ubuntu2.1 (станом на August 2026). Запис Ghostty додали в upstream у ncurses 6.5-20241228. Це новіша версія, тому apt install ncurses-term в Ubuntu 24.04 не може створити запис xterm-ghostty, скільки б разів ви його не запускали. tput -T <name> longname — це перевірка: команда виводить опис, якщо запис наявний, і завершується з кодом 3 через unknown terminal, якщо його немає.

Щоб інсталювати один запис у системі замість усього пакета, скопіюйте вихідний файл і скомпілюйте його від імені 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

Параметр -t у другій команді виділяє псевдотермінал, щоб sudo міг запросити пароль. Без нього sudo може завершитися з sudo: no tty present and no askpass program specified.

Нехай емулятор виконає передавання

Деякі емулятори мають допоміжний засіб, який автоматично виконує виправлення 2. kitty має kitten ssh: kitten ssh myserver підключається та автоматично копіює terminfo kitty на віддалений хост. У документації також наведено ручний варіант, infocmp -a xterm-kitty | ssh myserver tic -x -o \~/.terminfo /dev/stdin, де символ тильди екрановано з описаної вище причини. Ghostty документує infocmp -x xterm-ghostty | ssh YOUR-SERVER -- tic -x -, постачається із shell integration (ssh-env і ssh-terminfo), а також має дію +ssh, яка автоматизує обидва виправлення.

Ці допоміжні засоби виконують ті самі команди, які ви щойно запускали вручну. Знати ручний варіант усе одно важливо, оскільки допоміжний засіб не може працювати, якщо підключення починається в іншому місці — на jump host або всередині скрипту.

Коли помилка повертається

У sudo -i. Оболонка входу від імені root має HOME=/root, а sudo зберігає ваш TERM. Тепер ncurses шукає /root/.terminfo, де немає вашого запису, тому помилка повертається лише для root. Перевірте це за допомогою sudo -i env і перегляньте рядки HOME та TERM. Встановіть запис у системний каталог або розмістіть його копію в /root/.terminfo.

У tmux або screen. Вони встановлюють власний TERM для програм, запущених усередині, зазвичай screen-256color або tmux-256color. Старіший сервер знає screen-256color і може не знати tmux-256color, тому зовнішня оболонка працює, а всередині сесії все завершується помилкою. Причина та сама, але назва інша. Виконайте на сервері tput -T tmux-256color longname, щоб перевірити, який із двох варіантів він має. Термінальний робочий простір на основі tmux приховує цю проблему, доки ви не під’єднаєтеся до хоста, на якому її ще не виправлено.

На новому сервері. ~/.terminfo залежить від облікового запису та комп’ютера, тому після перебудови VPS знову починається з порожнього значення.

Екран відображається, але клавіші працюють неправильно. Якщо зображення коректне, але Home, End або функціональні клавіші вставляють зайві символи, ім’я зіставлено із записом, який не відповідає вашому терміналу. Послідовності клавіш беруться з того самого запису terminfo, що й параметри відображення, тому приблизний запис дає приблизні послідовності клавіш. Це типовий результат застосування способу 1 в емуляторі, послідовності клавіш якого відрізняються від xterm. Потрібно застосувати спосіб 2, оскільки лише фактичний запис вашого емулятора містить правильні послідовності.

FAQ

Чому через SSH я бачу лише «unknown terminal type»?

Тому що база даних із записом для вашого термінала розташована на сервері. Емулятор встановлює опис на машині, де він працює, тому локальні програми знаходять його без додаткових дій з вашого боку. SSH передає лише значення TERM, оскільки протокол передає цю назву разом із запитом на pseudo-terminal. Віддалений ncurses шукає назву у віддаленій базі даних і нічого не знаходить, тому initscr завершується помилкою, а програма зупиняється.

Чи можна виправити це без root на сервері?

Так. ncurses перевіряє $HOME/.terminfo перед будь-яким системним каталогом, тому запису в цьому каталозі достатньо для вашого облікового запису. Виконайте infocmp -x | ssh user@host -- tic -x - один раз для кожного сервера. tic записує дані у ваш домашній каталог, якщо не може записати їх до системного шляху. Для непривілейованого облікового запису це звичайна ситуація. Увійдіть на сервер і виконайте tput longname, щоб перевірити, чи тепер запис знаходиться.

Що я втрачу, якщо встановлю TERM=xterm-256color для хоста?

Усі можливості, які ваш емулятор описує додатково до запису xterm-256color, зокрема 24-бітний колір через RGB і стилізовані підкреслення через Smulx. Програми не бачать цих можливостей, тому використовують найближчий резервний варіант. Послідовності клавіш F-клавіш також можуть відрізнятися від послідовностей вашого реального термінала. Додайте це налаштування на клієнті у ~/.ssh/config, а не в .bashrc на сервері, оскільки це погіршить налаштування сеансів із терміналів, які вже працювали.

Чому помилка повертається після sudo -i?

sudo -i запускає login shell від імені root із HOME=/root, зберігаючи значення TERM. Тоді ncurses шукає запис у /root/.terminfo замість вашого домашнього каталогу і нічого не знаходить, тому root бачить ту саму помилку, якої ваш обліковий запис уже не бачить. Виконайте sudo -i env і перевірте рядки HOME та TERM. Скомпілюйте запис у системний каталог за допомогою sudo tic -x -o /usr/share/terminfo або скопіюйте його до /root/.terminfo.

Чи apt install ncurses-term завжди виправляє цю проблему?

Ні. Команда додає лише записи, які існували у версії ncurses, включеній до пакета вашого дистрибутива. Ubuntu 24.04 постачається з ncurses 6.4 (ncurses-bin 6.4+20240113-1ubuntu2.1, станом на August 2026), а запис Ghostty додали в upstream-версії ncurses 6.5-20241228, тому цей пакет не може його містити. Перед використанням пакета перевірте це за допомогою tput -T <name> longname. Якщо перевірка й далі повідомляє про невідомий термінал, додайте запис самостійно.

#terminfo#ssh#ncurses#tput#terminal