linux - SSH TERM detection
2014-07
My ssh config file has accept env set as:
AcceptEnv LANG LC_*
I am a bit confused how when I ssh through some clients my TERM variable is set as xterm256-color, and other clients TERM is set as vt100. My .bashrc and /etc/profile do not have anything that is setting the TERM variable.
$TERM
is special – it is not sent as an environment variable (which wouldn't make sense for non-Unix systems anyway), but rather as a special "terminal type" field when establishing a pseudo-terminal channel, per RFC 4254 § 6.2.
6.2. Requesting a Pseudo-Terminal
A pseudo-terminal can be allocated for the session by sending the following message.
byte SSH_MSG_CHANNEL_REQUEST uint32 recipient channel string "pty-req" boolean want_reply string TERM environment variable value (e.g., vt100) uint32 terminal width, characters (e.g., 80) uint32 terminal height, rows (e.g., 24) uint32 terminal width, pixels (e.g., 640) uint32 terminal height, pixels (e.g., 480) string encoded terminal modes
$TERM
is set by the terminal, that is, the parent process of the shell you are running locally. It is used by applications to determine what the capabilities of the terminal is, for example whether it supports colour. It's very useful to forward this to any other hosts you connect to, since otherwise they would lose this knowledge of the capabilities about the end user terminal.
See for example Prevent SSH client passing TERM environment variable to server?
I use WinSSHd on several Windows servers. To access them from my Mac (and presumably, just about any Unix-based terminal), I need to set the TERM
environment variable to cygwin
, e.g.:
TERM=cygwin ssh someserver.com
I can also use the .ssh/config
to set certain defaults for that server, such as a different user and non-default port:
host someserver.com
User SomeDifferentDude
Port 22222
However, I apparently can't set environment variables that way. I haven't found anything in man ssh_config
, anyway. Is there a way to set the default terminal emulation (and/or any environment variable) per host?
You would typically set the environment variable on the server side.
If WinSSHd is sufficiently like openssh (the usual unix implementation of ssh), you can define an environment file (~/.ssh/environment
on unix) and put TERM=cygwin
there.
You can also set the environment variable in your shell initialization file. Since you mention cygwin, this is presumably ~/.bash_profile
where ~
is your cygwin home directory. You should set it conditionally, in case you also use cygwin on other terminal types; for example, to set it only if you are logging in over ssh (again, assuming WinSSHd is sufficiently like openssh):
if [ -n "$SSH_CLIENT" ]; then
export TERM=cygwin
fi
It turns out there's a much better solution — WinSSHd supports Unix's terminfo
format, so all I had to do is copy the proper terminfo
file (in the case of OS X: xterm-color) into its directory, and the TERM=cygwin
setting become unnecessary.
You can use SendEnv TERM
to set the TERM on the server to be the same as the TERM on your local machine.