إصلاح خطأ «نوع الطرفية غير معروف» عبر SSH
إذا ظهر الخطأ «unknown terminal type» عبر SSH، تعلّم تثبيت إدخال 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 دائماً عند طلب طرفية زائفة، لأن البروتوكول يحتاج إليه". لذلك تحصل صدفة تسجيل الدخول على 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. ضع علامة الاقتباس حول tilde لكي توسّعها الصدفة البعيدة.
سجّل الدخول وتحقق:
ssh user@203.0.113.10
tput longname
ls -R ~/.terminfoتعني طباعة tput longname لوصف الطرفية أن البحث ينجح الآن، ويعرض ls الملف المجمّع داخل مجلد فرعي يحمل اسم الحرف الأول من اسم الطرفية. ثم شغّل top، أو راقب uptime باستخدام watch -n1، إذ يعيد الرسم عبر المكتبة نفسها، للتأكد من أن برنامج 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 من ذلك: يطبع الوصف عندما يكون الإدخال موجوداً، ويخرج 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 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 (ssh-env وssh-terminfo)، بالإضافة إلى إجراء +ssh ينفّذ الإصلاحين معاً.
تنفّذ هذه الأدوات المساعدة الأوامر نفسها التي نفّذتها يدوياً قبل قليل. ومع ذلك، تظل معرفة الصيغة اليدوية مهمة، لأن الأداة المساعدة لا تستطيع العمل عندما يبدأ الاتصال من مكان آخر، مثل jump host أو داخل script.
عند عودة الخطأ
في 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
لماذا تظهر لي رسالة "unknown terminal type" عبر SSH فقط؟
لأن قاعدة البيانات التي يجب أن تحتوي على إدخال الطرفية موجودة على الخادم. يثبّت المحاكي وصفه على الجهاز الذي يعمل عليه، لذلك تعثر البرامج المحلية عليه من دون أي إجراء منك. يرسل 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 قبل الاعتماد على الحزمة، وثبّت الإدخال بنفسك عندما يستمر الفحص في الإبلاغ عن طرفية غير معروفة.