30

I'm currently using Fedora 18 gnome-terminal, then started tmux multiplexer in it. After I connected to a CentOS 5 server via ssh command, I find:

  • ls result has no color
  • tmux, screen, hexedit, htop all failed to start with error message like:
    open terminal failed: missing or unsuitable terminal: screen-256color

It seems that ssh passes the $TERM environment variable to the server, but I can't find it in /etc/ssh/ssh_config file of Fedora 18.

Although I can manually change the $TERM variable on the server, each time I connect, it happens again. So how to prevent it?

LiuYan 刘研
  • 3,910
  • 5
  • 31
  • 34

7 Answers7

25

$TERM is to tell applications what terminal they're talking to so they know how to talk to it.

Change it to a value supported by the remote host and that matches as closely as possible your terminal (screen).

Most Linux systems should at least have a screen terminfo entry. If not, screen implements a superset of vt100 and vt100 is universal. So:

TERM=screen ssh host

or

TERM=vt100 ssh host

If you do need the 256 color support, you could try xterm-256color which should be close enough (screen supports 256 colors the same way xterm does) and tell applications your terminal application supports 256 colors and tell them how to use them.

Or you can install the terminfo entry on the remote host.

infocmp -x | ssh -t root@remote-host '
  cat > "$TERM.info" && tic -x "$TERM.info"'
Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
  • 2
    good to know `infocmp` and `tic`, once compiled, no need to temporarily change `$TERM` again. by the way, i just copied (rsync) `/usr/share/terminfo/s/screen-256color` from Fedora 18 to CentOS, it seems works ok (`rsync -tv /usr/share/terminfo/s/screen-256color root@the_host:/usr/share/terminfo/s`). – LiuYan 刘研 Mar 11 '13 at 11:14
  • forgot to mentioned, i ran `tmux` in gnome-terminal of Fedora 18, `tmux` changed `$TERM` value to `screen-256color` from `xterm-256color`. – LiuYan 刘研 Mar 11 '13 at 11:18
  • btw, can ssh works in this way: get the terminfo which host/server supported (not pushed into), then pickup one the client terminal can support? – LiuYan 刘研 Mar 11 '13 at 11:37
  • I found it amusing that this infocmp piped through ssh thing left a file called dumb.info in my home dir. – Dmitri DB May 18 '14 at 05:45
  • 4
    `infocmp | ssh -t root@remote-host 'cat > "$TERM.info" && tic "$TERM.info"'` can be shortened to `infocmp | ssh root@remote-host "tic -"`. This works because when you have a pipe it can be accessed as a file by using - and luckily pipes work across SSH. – Alan Jenkins Aug 31 '16 at 11:59
  • I copy the terminfo file from `/usr/share/terminfo` to the same place on the remote host. Is there any reason why using `infocmp` and `tic` would be preferable? – starfry Sep 09 '16 at 09:02
  • 1
    @starfry, I can't give you any guarantee that the binary format of the `tic` (terminfo compiler) generated files will be the same from one system to the next or that their location will be the same. `tic` may also make sure the permissions are correct or create intermediary directories where needed. – Stéphane Chazelas Sep 09 '16 at 09:37
  • The original command gave me `Pseudo-terminal will not be allocated because stdin is not a terminal.` error, while the shortened version actually worked for me. Alacritty works on ssh now =) – mazunki May 15 '20 at 02:37
21

In my case I simply added an alias to my .zshrc (.bashrc if using bash) on my local desktop:

alias ssh='TERM=xterm ssh'

If you already use an alias, adjust it to include the Environment assignment.

Michael Mrozek
  • 91,316
  • 38
  • 238
  • 232
zaTricky
  • 399
  • 3
  • 9
  • This solution is less desirable as it dumbs down the terminal support on the remote host, while uploading the terminal defintiions to your home directory on the server allows full terminal support in the remote connection. – Mark Stosberg Nov 16 '20 at 19:22
  • 2
    Ended up being the winner for me - I'm using kitty terminal, and none of the machines I SSH into have any support for that, so setting the TERM value back to a common base value is probably the best option in almost all cases – Phantomwhale Aug 09 '21 at 01:14
6

Changing $TERM might work, but I don't suggest this, it's only a workaround instead of a solution.

When I encounter this problem on my systems, I fix it by installing support for the most common terminal types to the remote system:

  • yum install ncurses-base for screen-256color on CentOS
  • yum install ncurses-term for screen-256color-bce on CentOS
  • apt install ncurses-base for both screen-256color and screen-256color-bce on Debian, Ubuntu and Mint

The ncurses-related packages also provide support for a lot of other terminals, and they are also available on all other large distributions. (But for my use-case and your question this should be enough info)

John Mee
  • 123
  • 5
Garo
  • 2,023
  • 9
  • 15
  • This may be the best answer, assuming desire/permission to install packages remotely. – Gringo Suave Aug 23 '20 at 23:53
  • Besides that you might not have permission to install packages remotely, such a package might not be available. For example Ubuntu 16.04 and 18.04 are still active LTS lines, but the terminal info for the `alacritty` terminal is not packaged until 20.04. – Mark Stosberg Nov 16 '20 at 19:25
2

The best solution is to end up with full terminal support during SSH sessions. To achieve this, upload your terminfo files to your home directory on the remote server.

Locally: Check your working TERM value:

 echo $TERM

In the following examples alacritty is used. Next, find local the terminfo files for your terminal:

 locate alacritty | grep terminfo

I found results under /usr/share/terminfo. Finally, upload the files to `~/.terminfo on the remote host.

 # On the remote host
 mkdir -p ~/.terminfo/a

 # Locally
 scp /usr/share/terminfo/a/alacritty* remotehost:.terminfo/a/

The terminfo format is a compiled format so simply copying the files may not work. If it doesn't work and infocmp and tic are available locally and remotely, you can use this method instead:

 infocmp -x | ssh -t root@remote-host 'cat > "$TERM.info" && tic -x "$TERM.info"'
Mark Stosberg
  • 7,420
  • 1
  • 32
  • 42
  • This is a really cool solution. The only negative is that it involves a bit of effort for a server you might only connect to once. For the other usecases it's robust and less guesswork. – zaTricky Nov 17 '20 at 08:41
0

I put this in my .bashrc on the remote host:

# 256-color mode not supported on this host
if echo $TERM | grep -q -- '-256color'; then
    echo -e '\n\n256-color mode not supported on this host.  Reverting TERM...\n'
    export TERM=`echo -n $TERM | sed 's/-256color//'`
fi

That way, both xterm-256color and screen-265color are handled properly. Also, I have it output the note so that if the server gets upgraded later and supports 256 colors, I won't end up banging my head against the wall wondering why my TERM variable gets changed when SSHing.

depquid
  • 3,801
  • 1
  • 20
  • 34
  • 1
    Or, don't start a subshell and another process: `export TERM=${TERM%%-256color}` – miken32 Dec 13 '18 at 16:06
  • If you are willing to use a solution that involves modifying files on every remote server you ssh into, you could instead install the desired terminal support files in `~/.terminfo` on all the remote hosts. – Mark Stosberg Nov 16 '20 at 15:19
0

What I did is add a function to my shell (.zshrc in my case) :

ssht() {
    ssh $1 'mkdir -p  ~/.terminfo/'${TERM:0:1} && scp /usr/share/terminfo/${TERM:0:1}/$TERM $1:~/.terminfo/${TERM:0:1}/$TERM && ssh $1
}

Then I ssht myserver or (ssht [email protected] if I did't put the user/host in .ssh/config) the first time I connect to a server.

It copies my current terminfo file to the server user's home .terminfo directory (after having created the directory) and then connects me.

0

See man ssh_config:

 SendEnv
         Specifies what variables from the local environ(7) should be sent
         to the server.  Note that environment passing is only supported
         for protocol 2.  The server must also support it, and the server
         must be configured to accept these environment variables.  Refer
         to AcceptEnv in sshd_config(5) for how to configure the server.
         Variables are specified by name, which may contain wildcard char‐
         acters.  Multiple environment variables may be separated by
         whitespace or spread across multiple SendEnv directives. The
         default is not to send any environment variables.

and man sshd_config:

 AcceptEnv
         Specifies what environment variables sent by the client will be
         copied into the session's environ(7).  See SendEnv in
         ssh_config(5) for how to configure the client.  Note that envi-
         ronment passing is only supported for protocol 2.  Variables are
         specified by name, which may contain the wildcard characters `*'
         and `?'.  Multiple environment variables may be separated by
         whitespace or spread across multiple AcceptEnv directives.  Be
         warned that some environment variables could be used to bypass
         restricted user environments.  For this reason, care should be
         taken in the use of this directive.  The default is not to accept
         any environment variables.

According to that, the default should be not to send any variables, but TERM seems to be special. It is send anyway.

Therefore you can either change TERM when calling ssh (like TERM=xterm ssh ...), change it after login (like in .bash_profile), or define the unknown TERM type on server side (assuming you have root access there). See other answer for details.

michas
  • 21,190
  • 4
  • 63
  • 93
  • 1
    Not setting `$TERM` will not really be any better than setting it to an unsupported value though. – Stéphane Chazelas Mar 11 '13 at 07:47
  • The literal question was, how to prevent sending TERM. - Answer: You cannot. - What he should do is setting it to a suitable value, yes. – michas Mar 11 '13 at 07:56
  • change `$TERM` temporarily may be a workaround, but i need to do it each time. by the way, it seems that both CentOS 5 and Fedora 18 Accept*Env* all locale environment variables (`LANG`, `LC_*`, ...) – LiuYan 刘研 Mar 11 '13 at 10:27