SSHの「unknown terminal type」を直す方法
SSHで「unknown terminal type」が出る原因と対処法を解説します。リモート側のterminfo不足を、root権限なしでホームディレクトリに登録して解決できます。
「unknown terminal type」の意味
SSH 経由で「unknown terminal type」エラーが表示される場合、TERM に設定された名前に一致するエントリが、サーバー上の terminfo データベースに存在しないことを意味します。端末エミュレーターがこの名前を設定するのは、使用しているラップトップ上です。その名前を認識する必要があるデータベースは、リモートマシン上にあります。検索に失敗すると、そのサーバー上のすべての curses プログラムは、何も描画しないまま終了します。使用中の端末が対応する機能の説明を取得できないためです。
端末エミュレーターの機能をすべて維持する方法は、サーバー上の ~/.terminfo に独自の terminfo エントリをコンパイルすることです。ncurses はシステムディレクトリより先にホームディレクトリを検索するため、root は不要で、他のユーザーには影響しません。
TERM は名前であり、terminfo はデータベースです
TERM には 1 つの文字列が格納され、その文字列はキーにすぎません。terminfo は端末の説明をコンパイルしたデータベースであり、プログラムはこのキーを使って適切な説明を検索します。説明には、端末が対応する色数、カーソルを 12 行 40 列へ移動するバイト列、F5 キーが送信するバイト列、装飾付き下線を描画できるかどうかなどが記録されています。Linux のほぼすべてのテキストユーザーインターフェースが基盤として使用するライブラリ ncurses は、起動時にこの説明を読み込みます。top、less、nano、watch などのプログラムは、この説明がなければ画面を 1 つも描画できません。
自分のエントリを確認します。
echo "$TERM"
tput longname
infocmp -1 | head -20tput longname は、TERM が指定する対象の、人間が読める説明を表示します。xterm-256color の場合は、次のように表示されます。
xterm with 256 colorsinfocmp -1 はエントリ全体を逆コンパイルし、機能を 1 行ずつ表示します。両方のコマンドが正常に動作すれば、このマシンのデータベースはこの端末を認識しています。SSH 接続の接続先でも必要なのは、この状態です。
SSH 経由でのみ失敗する理由
SSH は名前だけを送信し、それ以外は送信しません。クライアントが擬似端末を要求すると、その要求とともに TERM が送信されます。OpenSSH のマニュアルには、「擬似端末が要求された場合、プロトコル上必要なため、TERM=xterm-ghostty 環境変数は常に送信される」と明記されています。したがって、VPS 上のログインシェルには TERM=xterm-ghostty、xterm-kitty、または使用しているエミュレーターの名前が渡されます。その名前に対応する定義は、ノート PC 上のデータベースに残っています。エミュレーターが存在する前に構築されたサーバーは、その名前を認識したことがありません。SSH 接続自体が端末定義をコピーすることはありません。これは意図的な設計です。プロトコルが運ぶのは名前であり、機能一覧ではありません。
次のように、確実に存在しない名前を使って、自分のマシンでこの失敗を再現できます。
TERM=xterm-nosuchthing tput colors
echo "$?"tput: unknown terminal "xterm-nosuchthing"終了ステータスは 3 です。これは、ncurses が未知の端末タイプまたはデータベースの欠落として記録している状態です。すべての curses プログラムは同じ検索処理を実行するため、1 つの名前が欠落しているだけで、各プログラムから異なるメッセージが表示されます。ただし、原因は共通しています。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 ビルドが使用する一覧を表示できます。重要なのは Step 2 です。ホームディレクトリはシステムディレクトリより先に検索されるため、~/.terminfo 配下に 1 つファイルを置くだけで、そのアカウントの検索を修正できます。パッケージのインストールも root も必要ありません。
修正 1: サーバーが認識している TERM を使用する
最も早く問題を回避するには、1 回の接続で別の端末を指定します。
TERM=xterm-256color ssh user@203.0.113.10ノート PC の ~/.ssh/config で、そのホストに対して永続化します。
Host vps1
HostName 203.0.113.10
User deploy
SetEnv TERM=xterm-256colorSetEnv には、クライアント側で 2018 年 8 月にリリースされた OpenSSH 7.8 以降が必要です。TERM は、サーバーの許可を必要としない唯一の変数です。マニュアルには、「SendEnv と同様に、TERM 変数を除き、サーバーは環境変数を受け入れるよう準備されていなければならない」と記載されています。そのため、サーバー側に AcceptEnv 行がまったくない強化済みの sshd に対しても機能します。
代償は、エミュレーターが通常の xterm-256color 以外に示す機能がすべて失われることです。これには、RGB capability を通じて通知される 24-bit カラーや、Smulx による装飾下線が含まれます。プログラムからこれらの機能が見えなくなるため、256 色と通常の下線にフォールバックします。画面は動作します。ただし、選択した端末よりも機能が少なくなります。
サーバーの .bashrc に export TERM=xterm-256color を追加して解決しないでください。このファイルは、サーバーが認識している端末からの接続を含め、すべての接続で実行されます。そのため、問題なく動作していたセッションまで機能を低下させます。使用しているエミュレーターを把握できるクライアント側に、この上書きを設定してください。
修正 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はコマンドの各語を 1 つの文字列に結合し、それをリモートシェルに渡します。そのため、~を引用符で囲まないと、最初にローカルシェルで展開されます。その結果、アカウント名が異なる可能性のあるマシンへ、文字どおりの/home/yourname/.terminfoを送ることになります。ticは権限エラーで失敗するか、ncurses が検索しないパスへ書き込みます。チルダを引用符で囲むと、リモートシェルが展開します。
ログインして確認します。
ssh user@203.0.113.10
tput longname
ls -R ~/.terminfotput longnameが端末の定義を出力すれば、検索に成功しています。lsでは、端末名の先頭文字を名前とするサブディレクトリ内に、コンパイル済みファイルがあることを確認できます。次にtopを実行します。または、同じライブラリを使って画面を再描画するwatch -n1 uptimeを実行し、実際の curses プログラムが画面を描画できることを確認します。
必要な作業は、サーバーごとに 1 回実行することです。エントリは、1 台のマシンにある 1 つのアカウントのホームディレクトリに保存されます。VPS を再構築すると失われます。複数のサーバーを一度にプロビジョニングおよび管理するために使用している仕組みにこのコマンドを組み込み、新しいホストにエントリがコンパイル済みの状態で追加されるようにします。
修正 3: 拡張 terminfo データベースをインストールする
root があり、サーバー上のすべてのアカウントで名前を解決できるようにする場合は、次を実行します。
sudo apt update
sudo apt install ncurses-term
tput -T xterm-ghostty longnamencurses-term には、基本インストールで省かれる端末の説明が含まれています。root と他のすべてのユーザーで名前を解決できるようになります。修正 2 ではこの問題は解決しません。
ただし、使用している端末のエントリが、ディストリビューションにパッケージ化された ncurses のリリースに存在する場合に限り有効です。思い込まずに確認してください。Ubuntu 24.04 には、2026 年 8 月時点で ncurses-bin 6.4+20240113-1ubuntu2.1 が含まれています。Ghostty のエントリは、より新しい ncurses 6.5-20241228 で upstream に追加されました。そのため、Ubuntu 24.04 の apt install ncurses-term を何度実行しても、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.src2 つ目のコマンドにある -t は pseudo terminal を割り当てます。これにより、sudo はパスワードを要求できます。これがない場合、sudo は sudo: no tty present and no askpass program specified で終了することがあります。
エミュレーターに転送させる
一部のエミュレーターには、fix 2 を自動的に実行するヘルパーが用意されています。kitty には ssh kitten があり、kitten ssh myserver により接続時に kitty の terminfo をリモートホストへ自動的にコピーします。ドキュメントには、上記の理由でチルダをエスケープした手動実行形式 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 の場合。 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 を実行し、2 つのうちどちらが存在するか確認してください。tmux を中心に構成されたターミナル作業環境を使用すると、まだ修正していないホストに接続する日まで、この問題に気付きにくくなります。
新しいサーバーの場合。 ~/.terminfo はアカウントごと、マシンごとに存在するため、再構築した VPS では再び空の状態になります。
画面は表示されるが、キーが正常に動作しない場合。 表示に問題がないのに、Home、End、ファンクションキーで余分な文字が入力される場合は、解決された名前が端末と一致しないエントリを指しています。キーシーケンスは表示機能と同じ terminfo エントリから取得されるため、近似したエントリではキーも正しく動作しません。これは、キーシーケンスが xterm と異なるエミュレーターで修正 1 を行った場合によく発生します。修正 2 を使用してください。エミュレーター本来のエントリだけが、正しいキーシーケンスを持っているためです。
FAQ
SSH 経由ではなぜ「unknown terminal type」としか表示されないのですか?
端末のエントリを格納するデータベースは、サーバー側にある必要があるためです。端末エミュレーターは、実行されるマシンに自身の端末定義をインストールするため、ローカルプログラムは特別な設定なしでそれを見つけられます。SSH が送信するのは TERM の値だけです。プロトコルは、その名前を擬似端末の要求に含めるためです。リモート側の ncurses は、その名前をリモートのデータベースで検索しますが、見つかりません。そのため initscr が失敗し、プログラムが停止します。
サーバーで root になれなくても修正できますか?
はい。ncurses はすべてのシステムディレクトリより先に $HOME/.terminfo を検索するため、そこにエントリがあればアカウントで利用できます。サーバーごとに1回、infocmp -x | ssh user@host -- tic -x - を実行します。tic はシステムパスに書き込めない場合、ホームディレクトリに書き込みます。権限のないアカウントでは、通常この動作になります。ログインして tput longname を実行し、検索結果が解決することを確認します。
ホストに TERM=xterm-256color を設定すると、何が失われますか?
xterm-256color のエントリに加えて端末エミュレーターが提供するすべての機能が失われます。たとえば RGB による 24-bit カラーや、Smulx による装飾付き下線などです。プログラムからそれらの機能が見えなくなるため、最も近い代替機能が使われます。ファンクションキーのシーケンスも、実際の端末とは異なる場合があります。すでに正常に動作している端末からのセッションまで低機能化しないよう、設定はサーバーの .bashrc ではなく、クライアント側の ~/.ssh/config に記述します。
sudo -i の後にエラーが再発するのはなぜですか?
sudo -i は HOME=/root を使って 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(2026年8月時点では ncurses-bin 6.4+20240113-1ubuntu2.1)を出荷しています。Ghostty のエントリは ncurses 6.5-20241228 で上流に追加されたため、そのパッケージには含まれません。パッケージに依存する前に tput -T <name> longname で確認し、確認結果が unknown terminal のままなら、エントリを自分で用意します。