SSH पर unknown terminal type एरर कैसे ठीक करें
SSH कनेक्शन के दौरान unknown terminal type एरर तब आती है जब सर्वर आपके TERM नाम को नहीं पहचानता है। इसे ठीक करने के लिए अपनी होम डायरेक्टरी में terminfo एंट्री कंपाइल करें।
"unknown terminal type" का क्या अर्थ है
SSH पर "unknown terminal type" त्रुटि का अर्थ है कि TERM में दिया गया नाम सर्वर पर terminfo डेटाबेस में मौजूद नहीं है। आपका टर्मिनल एमुलेटर उस नाम को आपके लैपटॉप पर सेट करता है। जिस डेटाबेस को इसे पहचानना है, वह रिमोट मशीन पर स्थित होता है। जब यह लुकअप विफल हो जाता है, तो उस सर्वर पर चलने वाला प्रत्येक curses प्रोग्राम कुछ भी प्रदर्शित करने से पहले रुक जाता है, क्योंकि उसके पास यह विवरण नहीं होता कि आपका टर्मिनल क्या कर सकता है।
इसका समाधान जो आपके एमुलेटर की सभी विशेषताओं को बनाए रखता है, वह एक कमांड है: अपनी खुद की terminfo प्रविष्टि को सर्वर पर ~/.terminfo में कंपाइल करें। ncurses किसी भी सिस्टम डायरेक्टरी से पहले आपकी होम डायरेक्टरी में खोज करता है, इसलिए इसके लिए root एक्सेस की आवश्यकता नहीं होती और यह अन्य उपयोगकर्ताओं के लिए कुछ भी नहीं बदलता है।
TERM एक नाम है, terminfo एक डेटाबेस है
TERM में एक स्ट्रिंग होती है, और वह स्ट्रिंग केवल एक की (key) है। terminfo टर्मिनल विवरणों का एक संकलित (compiled) डेटाबेस है, और यह की (key) बताती है कि कोई प्रोग्राम सही विवरण कैसे खोजे। एक विवरण यह दर्ज करता है कि टर्मिनल में कितने रंग हैं, कौन से बाइट्स कर्सर को पंक्ति 12 कॉलम 40 पर ले जाते हैं, F5 की (key) कौन से बाइट्स भेजती है, और क्या यह स्टाइल वाली अंडरलाइन बना सकता है। ncurses, वह लाइब्रेरी जिस पर Linux के लगभग सभी टेक्स्ट यूजर इंटरफेस बने हैं, स्टार्टअप पर उस विवरण को पढ़ती है। top, less, nano और watch जैसे प्रोग्राम इसके बिना एक भी स्क्रीन पेंट नहीं कर सकते।
अपनी खुद की एंट्री देखें:
echo "$TERM"
tput longname
infocmp -1 | head -20tput longname उस विवरण का मानव-पठनीय (human-readable) रूप प्रिंट करता है जिसे TERM नाम देता है। xterm-256color के लिए यह प्रिंट करता है:
xterm with 256 colorsinfocmp -1 पूरी एंट्री को डीकंपाइल करता है और प्रति लाइन एक क्षमता (capability) प्रिंट करता है। यदि दोनों कमांड काम करते हैं, तो इस मशीन पर मौजूद डेटाबेस इस टर्मिनल को पहचानता है। SSH कनेक्शन के दूसरे छोर पर भी आपको यही स्थिति चाहिए।
यह केवल SSH पर ही क्यों विफल होता है
SSH केवल नाम भेजता है और कुछ नहीं। जब client एक pseudo terminal का अनुरोध करता है, तो TERM उस अनुरोध के साथ जाता है। OpenSSH manual स्पष्ट है: "जब भी pseudo-terminal का अनुरोध किया जाता है, TERM environment variable हमेशा भेजा जाता है क्योंकि protocol के लिए यह आवश्यक है"। इसलिए आपके VPS पर login shell को TERM=xterm-ghostty, या xterm-kitty, या आपके emulator द्वारा उपयोग किया जाने वाला कोई भी नाम प्राप्त होता है। उस नाम के पीछे का विवरण आपके laptop पर, आपके laptop के database में रहता है। आपके emulator के अस्तित्व में आने से पहले बने सर्वर ने उस नाम के बारे में कभी नहीं सुना है। SSH connection में कुछ भी terminal विवरणों की प्रतिलिपि नहीं बनाता है, और यह जानबूझकर किया गया है: protocol एक नाम ले जाता है, न कि क्षमताओं का डंप।
अपनी मशीन पर उस नाम के साथ विफलता को दोहराएं जो निश्चित रूप से मौजूद नहीं है:
TERM=xterm-nosuchthing tput colors
echo "$?"tput: unknown terminal "xterm-nosuchthing"Exit status 3 है, जिसे ncurses एक अज्ञात terminal प्रकार या गायब database के रूप में document करता है। प्रत्येक curses program एक ही lookup चलाता है, इसलिए एक गायब नाम हर program से अलग संदेश उत्पन्न करता है, जबकि उन सभी के पीछे एक ही कारण होता है। nano, Error opening terminal: xterm-nosuchthing. के साथ रुक जाता है, जो standard ncurses विफलता है जब यह startup पर विवरण लोड नहीं कर पाता है। vim, E558: Terminal entry not found in terminfo प्रिंट करता है। less, WARNING: terminal is not fully functional प्रिंट करता है। एक pager जो आधा काम करता है और एक editor जो शुरू होने से मना कर देता है, वे अलग-अलग bugs की तरह दिखते हैं। वे एक ही गायब file हैं।
ncurses कहाँ entry ढूँढता है
ncurses एक निश्चित क्रम में खोज करता है, जो terminfo(5) में प्रलेखित है:
$TERMINFO, यदि यह set है। केवल उसी directory में खोज की जाती है।$HOME/.terminfo।$TERMINFO_DIRSमें सूचीबद्ध प्रत्येक directory।- compiled-in locations, जिनमें Debian और Ubuntu पर
/etc/terminfo,/lib/terminfoऔर/usr/share/terminfoशामिल हैं।
सर्वर पर infocmp -D चलाएँ ताकि वह सूची प्रिंट हो सके जिसका उपयोग इसका अपना ncurses build करता है, बजाय ऊपर दिए गए paths पर भरोसा करने के। चरण 2 ही पूरी तरकीब है। आपकी home directory को किसी भी system directory से पहले खोजा जाता है, इसलिए ~/.terminfo के अंतर्गत एक file आपके account के लिए lookup को ठीक कर देती है, जिसमें न तो कोई package install करने की आवश्यकता होती है और न ही root access की।
उपाय 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-256colorSetEnv के लिए क्लाइंट पर OpenSSH 7.8 या उससे नया संस्करण आवश्यक है, जिसे अगस्त 2018 में रिलीज़ किया गया था। TERM एकमात्र ऐसा वेरिएबल है जिसे सर्वर की अनुमति की आवश्यकता नहीं होती है: मैनुअल के अनुसार "SendEnv के समान, TERM वेरिएबल के अपवाद के साथ, सर्वर को एनवायरनमेंट वेरिएबल स्वीकार करने के लिए तैयार रहना चाहिए"। इसलिए यह बिना किसी AcceptEnv लाइन वाले सुरक्षित sshd के खिलाफ भी काम करता है।
इसकी कीमत: साधारण xterm-256color से परे आपका एमुलेटर जो कुछ भी वर्णित करता है, वह सब। इसमें RGB क्षमता के माध्यम से विज्ञापित 24-बिट रंग और Smulx के माध्यम से स्टाइल की गई अंडरलाइन शामिल हैं। प्रोग्राम अब उन क्षमताओं को नहीं देख सकते हैं, इसलिए वे 256 रंगों और एक साधारण अंडरलाइन पर वापस आ जाते हैं। स्क्रीन काम करती है। यह बस आपके द्वारा चुने गए टर्मिनल की तुलना में कम सक्षम है।
इसे सर्वर पर अपनी .bashrc में export TERM=xterm-256color जोड़कर हल न करें। वह फ़ाइल हर कनेक्शन के लिए चलती है, जिसमें उन टर्मिनल से आने वाले कनेक्शन भी शामिल हैं जिनका नाम सर्वर जानता है, इसलिए यह उन सत्रों को डाउनग्रेड कर देती है जो पहले से ठीक थे। ओवरराइड को क्लाइंट पर रखें, जहाँ आप जानते हैं कि आप कौन सा एमुलेटर चला रहे हैं।
उपाय 2: अपनी terminfo entry को एक बार सर्वर पर भेजें
यह वह उपाय है जो आपके emulator को सुरक्षित रखता है। entry को स्थानीय रूप से decompile करें, उसे SSH के माध्यम से pipe करें और दूरस्थ सर्वर पर compile करें:
infocmp -x | ssh user@203.0.113.10 -- tic -x -infocmp -x आपके वर्तमान TERM के लिए entry को source text के रूप में print करता है, जिसमें extended (user-defined) capabilities भी शामिल होती हैं। tic -x उस source को सर्वर पर वापस binary description में compile करता है। दोनों तरफ -x का उपयोग महत्वपूर्ण है, क्योंकि इसके बिना Smulx जैसी capabilities transit के दौरान हट जाती हैं और आप अपने ही terminal की एक downgraded copy भेज देते हैं।
tic जब संभव हो तो system directory में लिखता है, और जब user के पास वहां write access न हो तो $HOME/.terminfo पर वापस आ जाता है। VPS पर एक सामान्य account को home directory मिलती है, जो कि आप चाहते भी हैं। आप destination का नाम भी रख सकते हैं:
infocmp -x | ssh user@203.0.113.10 -- tic -x -o '~/.terminfo' /dev/stdin~/.terminfo के चारों ओर लगे quotes सजावट नहीं हैं। ssh command के शब्दों को एक string में जोड़ता है और उसे remote shell को सौंप देता है, इसलिए बिना quotes वाला ~ पहले आपके local shell द्वारा expand हो जाता है। फिर आप एक literal /home/yourname/.terminfo ऐसी मशीन पर भेजते हैं जहाँ आपके account का नाम कुछ और हो सकता है। tic permission error के साथ विफल हो जाता है, या यह ऐसे path में लिखता है जिसे ncurses कभी search नहीं करता। tilde को quote करें और remote shell उसे expand करेगा।
Login करें और जाँचें:
ssh user@203.0.113.10
tput longname
ls -R ~/.terminfotput longname का आपके terminal का description print करना यह दर्शाता है कि lookup अब सफल है, और ls terminal नाम के पहले अक्षर के नाम वाली subdirectory के अंतर्गत compiled file को दिखाता है। फिर top चलाएं, या watch -n1 uptime, जो उसी library के माध्यम से redraw करता है, यह पुष्टि करने के लिए कि एक वास्तविक curses program screen को paint करता है।
इसकी लागत: प्रति सर्वर एक कदम, और entry एक मशीन पर एक account की home directory में रहती है। VPS को rebuild करने पर यह हट जाती है। इस command को उसमें डालें जिसका उपयोग आप एक साथ कई सर्वरों को provision और manage करने के लिए करते हैं ताकि एक नया host पहले से compiled entry के साथ तैयार मिले।
समाधान 3: extended terminfo database इंस्टॉल करें
यदि आपके पास root access है और आप चाहते हैं कि यह नाम मशीन के हर account के लिए resolve हो:
sudo apt update
sudo apt install ncurses-term
tput -T xterm-ghostty longnamencurses-term में वे terminal descriptions होते हैं जिन्हें base install में छोड़ दिया जाता है। यह root और अन्य सभी users के लिए नाम को ठीक करता है, जो कि समाधान 2 नहीं कर पाता।
यह केवल तभी मदद करता है जब आपके terminal की entry उस ncurses release में मौजूद हो जिसे आपके distribution ने package किया है, इसलिए अनुमान लगाने के बजाय जाँच करें। Ubuntu 24.04 में ncurses-bin 6.4+20240113-1ubuntu2.1 शामिल है (अगस्त 2026 तक)। Ghostty की entry ncurses 6.5-20241228 में जोड़ी गई थी, जो कि नया है, इसलिए Ubuntu 24.04 पर apt install ncurses-term कोई xterm-ghostty entry नहीं बना सकता, चाहे आप इसे कितनी भी बार चलाएं। tput -T <name> longname जाँच का तरीका है: यदि entry मौजूद है तो यह description print करता है, और यदि नहीं है तो exit status 3 के साथ unknown terminal देता है।
पूरे package के बजाय केवल एक single entry को system-wide इंस्टॉल करने के लिए, source को copy करें और root के रूप में compile करें:
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दूसरे command में -t एक pseudo terminal allocate करता है, ताकि sudo password के लिए prompt कर सके। इसके बिना, sudo संभवतः sudo: no tty present and no askpass program specified के साथ exit हो जाएगा।
इम्यूलेटर को ट्रांसफर करने दें
कुछ इम्यूलेटर ऐसे हेल्पर के साथ आते हैं जो आपके लिए फिक्स 2 को लागू कर देते हैं। kitty में एक ssh किटन (kitten) है: kitten ssh myserver रिमोट होस्ट से कनेक्ट होता है और kitty के terminfo को अपने आप कॉपी कर देता है। इसके डॉक्यूमेंटेशन में मैन्युअल तरीका भी दिया गया है, infocmp -a xterm-kitty | ssh myserver tic -x -o \~/.terminfo /dev/stdin, जिसमें ऊपर बताए गए कारण से टिल्ड (tilde) को एस्केप किया गया है। Ghostty में infocmp -x xterm-ghostty | ssh YOUR-SERVER -- tic -x - का डॉक्यूमेंटेशन है, और यह शेल इंटीग्रेशन (ssh-env और ssh-terminfo) के साथ-साथ एक +ssh एक्शन भी प्रदान करता है जो दोनों फिक्स को ऑटोमेट कर देता है।
ये हेल्पर वही कमांड चलाते हैं जिन्हें आपने अभी मैन्युअल रूप से चलाया है। मैन्युअल तरीके को जानना अभी भी महत्वपूर्ण है, क्योंकि जब कनेक्शन कहीं और से शुरू होता है, जैसे कि जंप होस्ट पर या किसी स्क्रिप्ट के अंदर, तो हेल्पर काम नहीं कर सकता।
जब त्रुटि वापस आती है
sudo -i के अंतर्गत। root के रूप में एक login shell में HOME=/root होता है, और sudo आपके TERM को सुरक्षित रखता है। ncurses अब /root/.terminfo को खोजता है, जिसमें आपकी entry मौजूद नहीं है, इसलिए विफलता केवल root के लिए वापस आती है। sudo -i env के साथ पुष्टि करें और HOME तथा TERM पंक्तियों को पढ़ें। entry को system directory में install करें, या /root/.terminfo में एक प्रतिलिपि रखें।
tmux या screen के अंदर। ये अपने अंदर चलने वाले प्रोग्रामों के लिए अपना स्वयं का TERM सेट करते हैं, जो आमतौर पर screen-256color या tmux-256color होता है। एक पुराना सर्वर screen-256color को जानता है और शायद tmux-256color को न पहचाने, इसलिए बाहरी shell ठीक काम करता है जबकि session के अंदर सब कुछ विफल हो जाता है। कारण समान है, नाम अलग है। यह देखने के लिए कि सर्वर पर दोनों में से कौन सा मौजूद है, tput -T tmux-256color longname चलाएं। एक tmux के इर्द-गिर्द निर्मित टर्मिनल वर्कबेंच इसे तब तक छिपाए रखता है जब तक कि आप किसी ऐसे host से attach नहीं होते जिसे आपने अभी तक ठीक नहीं किया है।
एक नए सर्वर पर। ~/.terminfo प्रति खाता और प्रति मशीन होता है, इसलिए एक rebuilt VPS फिर से खाली शुरू होता है।
Screen draw होता है, keys गलत व्यवहार करती हैं। यदि display ठीक है लेकिन Home, End या function keys अतिरिक्त characters डाल रहे हैं, तो नाम एक ऐसी entry पर resolve हुआ है जो आपके टर्मिनल से मेल नहीं खाती। Key sequences उसी terminfo entry से आते हैं जिससे drawing capabilities आती हैं, इसलिए एक अनुमानित entry अनुमानित keys देती है। यह एक ऐसे emulator पर fix 1 का सामान्य परिणाम है जिसकी key sequences xterm से भिन्न हैं। Fix 2 इसका उत्तर है, क्योंकि केवल आपके emulator की वास्तविक entry ही सही sequences रखती है।
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 एंट्री से परे आपके एमुलेटर द्वारा वर्णित हर क्षमता, जैसे RGB के माध्यम से 24-बिट कलर और Smulx के माध्यम से स्टाइल वाली अंडरलाइन। प्रोग्राम उन क्षमताओं को नहीं देख पाते हैं, इसलिए वे निकटतम फॉलबैक का उपयोग करते हैं। फंक्शन-की सीक्वेंस भी आपके वास्तविक टर्मिनल से भिन्न हो सकते हैं। इस सेटिंग को सर्वर पर .bashrc में रखने के बजाय क्लाइंट पर ~/.ssh/config में रखें, अन्यथा यह उन टर्मिनलों से सेशन को डाउनग्रेड कर देगा जो पहले से काम कर रहे थे।
sudo -i के बाद त्रुटि वापस क्यों आती है?
sudo -i आपके TERM मान को बनाए रखते हुए, HOME=/root के साथ root के रूप में एक लॉगिन शेल शुरू करता है। 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 तक ncurses-bin 6.4+20240113-1ubuntu2.1) आता है, और Ghostty की एंट्री अपस्ट्रीम ncurses 6.5-20241228 में जोड़ी गई थी, इसलिए वह पैकेज इसे शामिल नहीं कर सकता। पैकेज पर निर्भर होने से पहले tput -T <name> longname के साथ जांच करें, और जब जांच अभी भी अज्ञात टर्मिनल की रिपोर्ट करे तो एंट्री को स्वयं शिप करें।