SSD Nodes Learn 🎉 VPS $5.50/ماہ سے
تعلیمی Matt Connorتحریر: Matt Connor

SSH میں 'unknown terminal type' کی خرابی درست کریں

SSH میں 'unknown terminal type' اس وقت آتا ہے جب server کا terminfo، TERM نام نہ پہچانے۔ اپنی home directory میں entry compile کریں، root کی ضرورت نہیں۔

"unknown terminal type" کا مطلب

SSH کے ذریعے ظاہر ہونے والی "unknown terminal type" کی خرابی کا مطلب ہے کہ TERM میں موجود نام کو server کے terminfo database میں کوئی matching entry نہیں ملتی۔ آپ کا terminal emulator یہ نام آپ کے laptop پر set کرتا ہے۔ اسے recognise کرنے والا database remote machine پر موجود ہوتا ہے۔ lookup ناکام ہونے پر اس server کا ہر curses program کچھ بھی draw کرنے سے پہلے رک جاتا ہے، کیونکہ اسے آپ کے terminal کی صلاحیتوں کی کوئی description نہیں ملتی۔

اس حل سے آپ کے terminal emulator کی تمام features برقرار رہتی ہیں: صرف ایک command کے ذریعے اپنی terminfo entry کو server پر ~/.terminfo میں compile کریں۔ ncurses کسی بھی system directory سے پہلے آپ کی home directory میں تلاش کرتا ہے، اس لیے root کی ضرورت نہیں ہوتی اور دوسرے users کے لیے کچھ تبدیل نہیں ہوتا۔

TERM نام ہے، terminfo ڈیٹابیس ہے

TERM میں ایک string ہوتی ہے، اور وہ string صرف ایک key ہوتی ہے۔ terminfo ٹرمینل کی descriptions کا compiled database ہے، اور key کے ذریعے پروگرام درست description تلاش کرتا ہے۔ ایک description میں یہ درج ہوتا ہے کہ ٹرمینل کتنے colours رکھتا ہے، کون سے bytes cursor کو row 12، column 40 پر لے جاتے ہیں، F5 key کون سے bytes بھیجتی ہے، اور آیا ٹرمینل styled underline دکھا سکتا ہے۔ ncurses وہ library ہے جس پر Linux کے تقریباً تمام text user interfaces بنے ہیں، اور یہ startup کے وقت description پڑھتی ہے۔ top، less، nano اور watch جیسے پروگرام اس کے بغیر ایک screen بھی نہیں بنا سکتے۔

اپنی entry دیکھیں:

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

tput longname اس چیز کی human-readable description دکھاتا ہے جسے TERM نام دیتا ہے۔ xterm-256color کے لیے یہ دکھاتا ہے:

xterm with 256 colors

infocmp -1 پوری entry کو decompile کرکے ہر capability کو الگ line پر دکھاتا ہے۔ اگر دونوں commands کامیابی سے چلیں تو اس machine کا database اس terminal کو جانتا ہے۔ SSH connection کے دوسری طرف بھی یہی state درکار ہے۔

یہ صرف SSH کے ذریعے کیوں خراب ہوتا ہے

SSH نام بھیجتا ہے، اس کے علاوہ کچھ نہیں بھیجتا۔ جب client pseudo terminal کی درخواست کرتا ہے تو TERM اسی درخواست کے ساتھ بھیجا جاتا ہے۔ OpenSSH manual اس بارے میں واضح ہے: "the TERM environment variable is always sent whenever a pseudo-terminal is requested as it is required by the protocol"۔ اس لیے VPS پر آپ کے login shell کو TERM=xterm-ghostty، یا xterm-kitty، یا آپ کے emulator کا استعمال کردہ کوئی اور نام ملتا ہے۔ اس نام کے پیچھے موجود description آپ کے laptop پر، اسی کے database میں رہتی ہے۔ آپ کے emulator کے وجود میں آنے سے پہلے بنے ہوئے server نے یہ نام کبھی نہیں سنا۔ SSH connection خود terminal descriptions کو copy نہیں کرتا، اور یہ جان بوجھ کر ایسا ہے: protocol نام منتقل کرتا ہے، capabilities کا مکمل dump نہیں۔

اپنی machine پر ایسے نام کے ساتھ failure دوبارہ پیدا کریں جو یقینی طور پر موجود نہیں:

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

Exit status 3 ہے۔ ncurses اسے unknown terminal type یا missing database کے طور پر document کرتا ہے۔ ہر curses program یہی lookup کرتا ہے، اس لیے ایک missing name ہر program میں مختلف message پیدا کرتا ہے، لیکن بنیادی وجہ ایک ہی ہوتی ہے۔ nano، Error opening terminal: xterm-nosuchthing. پر رک جاتا ہے۔ یہ startup کے وقت description load نہ کر سکنے پر ncurses کی standard failure ہے۔ vim، E558: Terminal entry not found in terminfo print کرتا ہے۔ less، WARNING: terminal is not fully functional print کرتا ہے۔ ایسا pager جو جزوی طور پر کام کرے اور ایسا editor جو start ہونے سے انکار کرے، بظاہر غیر متعلق bugs لگتے ہیں۔ اصل میں دونوں کے پیچھے ایک ہی missing file ہوتی ہے۔

ncurses اندراج کہاں تلاش کرتا ہے

ncurses ایک مقررہ ترتیب میں تلاش کرتا ہے، جس کی دستاویزات terminfo(5) میں موجود ہیں:

  1. $TERMINFO، اگر یہ set ہو۔ صرف اسی directory میں تلاش کی جاتی ہے۔
  2. $HOME/.terminfo۔
  3. $TERMINFO_DIRS میں درج ہر directory۔
  4. compile کے وقت شامل کی گئی locations، جن میں Debian اور Ubuntu پر /etc/terminfo، /lib/terminfo اور /usr/share/terminfo شامل ہیں۔

Server پر infocmp -D چلائیں تاکہ اس کی اپنی ncurses build کے زیرِ استعمال فہرست ظاہر ہو۔ اوپر دیے گئے paths پر انحصار نہ کریں۔ اصل حل Step 2 میں ہے۔ آپ کی home directory کو system directory سے پہلے تلاش کیا جاتا ہے، اس لیے ~/.terminfo کے اندر صرف ایک file رکھنے سے آپ کے account کے لیے lookup درست ہو جاتا ہے۔ اس کے لیے package install یا root کی ضرورت نہیں۔

درست کریں 1: ایسا TERM استعمال کریں جسے سرور پہلے سے جانتا ہو

فوری طور پر مسئلہ دور کرنے کا تیز ترین طریقہ یہ ہے کہ ایک connection کے لیے مختلف terminal کا نام دیں:

TERM=xterm-256color ssh user@203.0.113.10

اپنے laptop پر ~/.ssh/config میں اس host کے لیے اسے مستقل بنائیں:

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

SetEnv کے لیے client پر OpenSSH 7.8 یا اس کے بعد کا ورژن درکار ہے، جو August 2018 میں جاری ہوا تھا۔ TERM وہ واحد variable ہے جس کے لیے server کی اجازت درکار نہیں ہوتی: manual میں لکھا ہے، "اسی طرح SendEnv کے لیے، لیکن TERM variable کے استثنا کے ساتھ، server کو environment variable قبول کرنے کے لیے تیار ہونا چاہیے۔" اس لیے یہ hardened sshd کے ساتھ بھی کام کرتا ہے، خواہ اس میں AcceptEnv کی کوئی line موجود نہ ہو۔

اس کا نقصان یہ ہے کہ plain xterm-256color سے آگے emulator کی بیان کردہ تمام خصوصیات ختم ہو جاتی ہیں۔ اس میں RGB capability کے ذریعے ظاہر کیا جانے والا 24-bit colour اور Smulx کے ذریعے styled underlines بھی شامل ہیں۔ Programs اب ان capabilities کو نہیں دیکھ سکتے، اس لیے وہ 256 colours اور سادہ underline پر واپس آ جاتے ہیں۔ Screen کام کرتی ہے۔ بس یہ آپ کے منتخب کردہ terminal کے مقابلے میں کم صلاحیت رکھتی ہے۔

Server پر اپنے .bashrc میں export TERM=xterm-256color شامل کر کے یہ مسئلہ حل نہ کریں۔ یہ file ہر connection کے لیے چلتی ہے، بشمول ان terminals سے آنے والے connections جن کا نام server جانتا ہے۔ اس طرح وہ sessions بھی کم صلاحیت والے ہو جاتے ہیں جو پہلے سے درست کام کر رہے تھے۔ Override کو client پر رکھیں، جہاں آپ کو معلوم ہوتا ہے کہ آپ کون سا emulator چلا رہے ہیں۔

حل 2: اپنی terminfo entry ایک بار server پر بھیجیں

یہ وہ حل ہے جس سے آپ کا 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 کو server پر دوبارہ binary description میں compile کرتا ہے۔ دونوں اطراف -x اہم ہے، کیونکہ اس کے بغیر Smulx جیسی capabilities راستے میں drop ہو جاتی ہیں اور آپ اپنے terminal کی کم صلاحیتوں والی 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 words کو ایک string میں جوڑ کر remote shell کے حوالے کرتا ہے، اس لیے unquoted ~ پہلے آپ کے local shell سے expand ہوتا ہے۔ اس کے بعد آپ کسی ایسی machine کو 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 ~/.terminfo

tput longname کا آپ کے terminal کی description print کرنا ظاہر کرتا ہے کہ lookup اب کامیاب ہے، اور ls compiled file کو terminal name کے پہلے حرف کے نام سے بنائی گئی subdirectory کے اندر دکھاتا ہے۔ پھر top چلائیں، یا watch -n1 uptime، جو اسی library کے ذریعے screen دوبارہ draw کرتا ہے، تاکہ تصدیق ہو کہ کوئی حقیقی curses program screen کو paint کر رہا ہے۔

اس کی لاگت: ہر server کے لیے ایک step، اور entry ایک machine پر ایک account کی home directory میں رہتی ہے۔ VPS کو دوبارہ build کرنے پر یہ ختم ہو جاتی ہے۔ command کو اس عمل میں شامل کریں جسے آپ ایک ساتھ متعدد servers کی provisioning اور management کے لیے استعمال کرتے ہیں، تاکہ نیا host آتے ہی entry پہلے سے compiled ہو۔

درست کریں 3: توسیعی terminfo database انسٹال کریں

اگر آپ کے پاس root رسائی ہے اور آپ چاہتے ہیں کہ یہ نام سسٹم کے ہر account کے لیے resolve ہو:

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

ncurses-term میں وہ terminal descriptions شامل ہوتی ہیں جو base install میں رہ جاتی ہیں۔ اس سے root اور ہر دوسرے user کے لیے نام درست ہو جاتا ہے، جبکہ fix 2 ایسا نہیں کرتا۔

یہ صرف اس وقت مددگار ہے جب آپ کے terminal کا entry آپ کی distribution کے فراہم کردہ ncurses release میں موجود ہو۔ اس لیے فرض کرنے کے بجائے جانچ کریں۔ Ubuntu 24.04 میں ncurses-bin 6.4+20240113-1ubuntu2.1 شامل ہے (August 2026 تک)۔ Ghostty کا entry upstream میں ncurses 6.5-20241228 میں شامل کیا گیا تھا، جو اس سے نیا ہے۔ اس لیے Ubuntu 24.04 پر apt install ncurses-term کتنی ہی بار چلائیں، یہ xterm-ghostty entry تیار نہیں کر سکتا۔ tput -T <name> longname جانچ کا طریقہ ہے: entry موجود ہو تو یہ description دکھاتا ہے، اور موجود نہ ہو تو unknown terminal کو exit status 3 کے ساتھ ختم کرتا ہے۔

پورا 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 مختص کرتا ہے، تاکہ sudo password کا prompt دکھا سکے۔ اس کے بغیر sudo ممکن ہے کہ sudo: no tty present and no askpass program specified کے ساتھ ختم ہو جائے۔

ایمولیٹر سے منتقلی کروائیں

کچھ ایمولیٹرز ایسا معاون فراہم کرتے ہیں جو fix 2 خود انجام دیتا ہے۔ kitty میں ssh kitten موجود ہے: kitten ssh myserver کنکشن قائم کرتا ہے اور kitty کی terminfo خودکار طور پر remote host پر کاپی کرتا ہے۔ اس کی دستاویزات دستی طریقہ بھی بتاتی ہیں، یعنی infocmp -a xterm-kitty | ssh myserver tic -x -o \~/.terminfo /dev/stdin، جس میں اوپر بیان کردہ وجہ سے tilde کو escape کیا گیا ہے۔ Ghostty میں infocmp -x xterm-ghostty | ssh YOUR-SERVER -- tic -x - درج ہے، اور یہ shell integration (ssh-env اور ssh-terminfo) کے ساتھ +ssh action بھی فراہم کرتا ہے، جو دونوں fixes خودکار طور پر انجام دیتے ہیں۔

یہ معاون وہی commands چلاتے ہیں جو آپ نے ابھی دستی طور پر چلائی ہیں۔ دستی طریقہ جاننا پھر بھی ضروری ہے، کیونکہ جب connection کسی اور جگہ، jump host پر یا کسی script کے اندر سے شروع ہو تو helper کارروائی نہیں کر سکتا۔

جب خرابی دوبارہ ظاہر ہو

sudo -i کے تحت۔ root کے طور پر login shell میں HOME=/root ہوتا ہے، اور sudo آپ کا TERM برقرار رکھتا ہے۔ ncurses اب /root/.terminfo میں تلاش کرتا ہے، جہاں آپ کی entry موجود نہیں، اس لیے خرابی صرف root کے لیے دوبارہ ظاہر ہوتی ہے۔ sudo -i env سے تصدیق کریں اور HOME اور TERM والی سطریں پڑھیں۔ entry کو system directory میں install کریں، یا اس کی ایک copy /root/.terminfo میں رکھیں۔

tmux یا screen کے اندر۔ یہ اپنے اندر چلنے والے پروگراموں کے لیے الگ TERM مقرر کرتے ہیں، جو عموماً screen-256color یا tmux-256color ہوتا ہے۔ پرانا server screen-256color کو جانتا ہے اور ممکن ہے tmux-256color کو نہ جانتا ہو، اس لیے بیرونی shell درست رہتا ہے جبکہ session کے اندر موجود ہر چیز ناکام ہو جاتی ہے۔ وجہ وہی ہے، صرف نام مختلف ہے۔ server پر tput -T tmux-256color longname چلائیں تاکہ معلوم ہو سکے کہ اس میں ان دونوں میں سے کون سا موجود ہے۔ tmux پر مبنی terminal workbench اس مسئلے کو اس دن تک چھپائے رکھتا ہے جب آپ ایسے host سے attach کرتے ہیں جسے ابھی درست نہیں کیا گیا۔

نئے server پر۔ ~/.terminfo ہر account اور ہر machine کے لیے الگ ہوتا ہے، اس لیے rebuilt VPS دوبارہ خالی حالت میں شروع ہوتا ہے۔

اسکرین درست دکھائی دیتی ہے، مگر keys غلط کام کرتی ہیں۔ اگر display درست ہو لیکن Home، End یا function keys غیر متعلقہ characters داخل کریں، تو resolved نام ایسی entry سے متعلق ہے جو آپ کے terminal سے مطابقت نہیں رکھتی۔ Key sequences بھی drawing capabilities کی طرح اسی terminfo entry سے آتی ہیں، اس لیے تقریباً درست entry تقریباً درست keys فراہم کرتی ہے۔ xterm سے مختلف key sequences والے emulator پر fix 1 کا عام نتیجہ یہی ہوتا ہے۔ اس کا حل fix 2 ہے، کیونکہ صرف آپ کے emulator کی حقیقی entry ہی درست sequences رکھتی ہے۔

FAQ

مجھے SSH پر صرف "unknown terminal type" کیوں نظر آتا ہے؟

کیونکہ آپ کے terminal کی entry رکھنے والا database server پر موجود ہوتا ہے۔ آپ کا emulator اپنی description اس machine پر install کرتا ہے جہاں وہ چلتا ہے، اس لیے local programs اسے آپ کی کسی اضافی کارروائی کے بغیر تلاش کر لیتے ہیں۔ SSH صرف TERM کی value بھیجتا ہے، کیونکہ protocol pseudo-terminal request کے ساتھ یہ نام منتقل کرتا ہے۔ remote ncurses remote database میں اس نام کو تلاش کرتا ہے، مگر اسے کچھ نہیں ملتا۔ اس لیے initscr fail ہو جاتا ہے اور program رک جاتا ہے۔

کیا میں server پر root کے بغیر اسے ٹھیک کر سکتا ہوں؟

جی ہاں۔ ncurses کسی بھی system directory سے پہلے $HOME/.terminfo میں تلاش کرتا ہے، اس لیے وہاں موجود entry آپ کے account کے لیے کافی ہے۔ ہر server پر ایک بار infocmp -x | ssh user@host -- tic -x - چلائیں۔ جب tic system path میں write نہیں کر سکتا تو یہ آپ کی home directory میں لکھتا ہے، جو unprivileged account کے لیے معمول کی صورت ہے۔ login کریں اور lookup کے resolve ہونے کی تصدیق کے لیے tput longname چلائیں۔

کسی host کے لیے TERM=xterm-256color set کرنے سے میں کیا کھو دیتا ہوں؟

آپ کا emulator xterm-256color entry کے علاوہ جن capabilities کو describe کرتا ہے، وہ سب متاثر ہوتی ہیں، مثلاً RGB کے ذریعے 24-bit colour اور Smulx کے ذریعے styled underlines۔ Programs ان capabilities کو دیکھ نہیں سکتے، اس لیے وہ قریب ترین fallback استعمال کرتے ہیں۔ Function-key sequences بھی آپ کے حقیقی terminal سے مختلف ہو سکتی ہیں۔ یہ setting server کے .bashrc میں رکھنے کے بجائے client کے ~/.ssh/config میں رکھیں، کیونکہ server والی setting ان terminals سے آنے والے sessions کو بھی downgrade کر دے گی جو پہلے سے درست کام کر رہے تھے۔

sudo -i کے بعد error دوبارہ کیوں آتا ہے؟

sudo -i HOME=/root کے ساتھ root کی login shell شروع کرتا ہے، جبکہ آپ کی TERM value برقرار رکھتا ہے۔ اس کے بعد ncurses آپ کی اپنی home directory کے بجائے /root/.terminfo میں تلاش کرتا ہے اور اسے کچھ نہیں ملتا، اس لیے root کو وہی failure نظر آتا ہے جو آپ کے account کو اب نظر نہیں آتا۔ sudo -i env چلائیں اور HOME اور TERM lines چیک کریں۔ entry کو system directory میں sudo tic -x -o /usr/share/terminfo کے ذریعے compile کریں، یا اسے /root/.terminfo میں copy کریں۔

کیا apt install ncurses-term اسے ہمیشہ ٹھیک کر دیتا ہے؟

نہیں۔ یہ صرف وہ entries شامل کرتا ہے جو آپ کی distribution کے packaged ncurses release میں موجود تھیں۔ Ubuntu 24.04، ncurses 6.4 (ncurses-bin 6.4+20240113-1ubuntu2.1، August 2026 تک) ship کرتا ہے، جبکہ Ghostty کی entry upstream میں ncurses 6.5-20241228 میں شامل کی گئی تھی، اس لیے اس package میں یہ entry موجود نہیں ہو سکتی۔ Package پر انحصار کرنے سے پہلے tput -T <name> longname سے چیک کریں، اور اگر check اب بھی unknown terminal رپورٹ کرے تو entry خود ship کریں۔

#terminfo#ssh#ncurses#tput#terminal