Ошибка unknown terminal type при подключении по SSH
Ошибка возникает из-за отсутствия записи в базе terminfo на сервере. Исправьте проблему без прав root, скомпилировав описание терминала в домашнем каталоге пользователя.
Что означает ошибка "unknown terminal type"
Ошибка неизвестного типа терминала при подключении по 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 -20tput longname выводит описание в человекочитаемом виде для того, что указано в TERM. Для xterm-256color она выводит:
xterm with 256 colorsinfocmp -1 декомпилирует всю запись и выводит по одной возможности на строку. Если обе команды работают, значит, база данных на этой машине знает данный терминал. Это состояние, которое вам необходимо иметь и на удаленной стороне SSH-соединения.
Почему это ломается только по SSH
SSH передает только имя и ничего больше. Когда клиент запрашивает псевдотерминал, TERM отправляется вместе с этим запросом. Руководство OpenSSH прямо указывает: «переменная окружения TERM всегда отправляется при запросе псевдотерминала, так как это требуется протоколом». Поэтому ваша оболочка входа на 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):
$TERMINFO, если эта переменная установлена. Выполняется поиск только в этом каталоге.$HOME/.terminfo.- Все каталоги, перечисленные в
$TERMINFO_DIRS. - Скомпилированные пути, которые в 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 longnamencurses-term содержит описания терминалов, которые отсутствуют в базовой установке. Это исправляет имя для root и для всех остальных пользователей, чего не делает исправление 2.
Это помогает только в том случае, если запись вашего терминала присутствует в версии ncurses, включенной в ваш дистрибутив, поэтому сначала проверьте, а не предполагайте. Ubuntu 24.04 поставляет ncurses-bin 6.4+20240113-1ubuntu2.1 (по состоянию на август 2026 года). Запись для Ghostty была добавлена в апстрим ncurses 6.5-20241228, что является более новой версией, поэтому apt install ncurses-term в Ubuntu 24.04 не сможет создать запись xterm-ghostty, сколько бы раз вы ее ни запускали. tput -T <name> longname — это способ проверки: команда выводит описание, если запись существует, и unknown terminal с кодом завершения 3, если ее нет.
Чтобы установить одну запись для всей системы вместо всего пакета, скопируйте исходный код и скомпилируйте его от имени 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 есть ssh kitten: 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 - и включает интеграцию с оболочкой (ssh-env и ssh-terminfo), а также действие +ssh, которые автоматизируют оба исправления.
Эти вспомогательные инструменты выполняют те же команды, которые вы только что ввели вручную. Знание ручного способа по-прежнему важно, так как инструмент не может сработать, если соединение начинается в другом месте, например, на jump host или внутри скрипта.
Когда ошибка возвращается
В условиях sudo -i. Login shell для пользователя 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, так как протокол переносит это имя вместе с запросом на создание псевдотерминала. Удаленная библиотека ncurses ищет это имя в своей базе данных, не находит его, поэтому вызов initscr завершается с ошибкой, и программа прекращает работу.
Можно ли исправить это без прав root на сервере?
Да. Библиотека ncurses ищет данные в $HOME/.terminfo перед обращением к системным директориям, поэтому записи в этой папке достаточно для работы под вашей учетной записью. Выполните infocmp -x | ssh user@host -- tic -x - один раз для каждого сервера. Утилита tic записывает данные в домашнюю директорию, если у нее нет прав на запись в системные пути, что является стандартной ситуацией для непривилегированного пользователя. Перезайдите в систему и выполните tput longname, чтобы убедиться, что поиск теперь работает корректно.
Что я теряю, устанавливая TERM=xterm-256color для хоста?
Вы теряете все возможности, которые ваш эмулятор описывает сверх записи xterm-256color, например, поддержку 24-битного цвета через RGB и стилизованные подчеркивания через Smulx. Программы не видят эти возможности и используют ближайший доступный вариант. Последовательности функциональных клавиш также могут отличаться от тех, что использует ваш реальный терминал. Устанавливайте эту настройку на клиенте в ~/.ssh/config, а не в .bashrc на сервере, так как это ухудшит работу сессий для терминалов, которые уже функционировали корректно.
Почему ошибка возвращается после sudo -i?
Команда sudo -i запускает оболочку входа от имени 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, по состоянию на август 2026 года), а запись для Ghostty была добавлена в основную ветку ncurses только в версии 6.5-20241228, поэтому в текущем пакете ее быть не может. Проверяйте наличие записи с помощью tput -T <name> longname, прежде чем полагаться на пакет, и добавляйте описание терминала самостоятельно, если проверка по-прежнему сообщает, что терминал неизвестен.