33

On my local terminal, I have TERM=konsole-256color, but not all remote machine I connect to have this definition.

Is it possible to make ssh change the TERM on remote machine? Without changing .bash* scripts on remote machine, just by changing configuration on my local desktop?

5 Answers5

18

I have added the following alias to my .bashrc file. It uses O G's answer but wraps it in an alias. Works like a charm ;)

# Force xterm-color on ssh sessions
alias ssh='TERM=xterm-color ssh'
Johan
  • 281
  • 2
  • 3
  • This works if I use ssh from a terminal. But I also have several scripts that run ssh, and the alias isn't expanded for them. Is there any way I can avoid making a seperate alias for each of them? – Thayne Sep 11 '17 at 19:03
  • 1
    If your script needs a specific TERM value, I think it would be best to just set that varialble in the script itself. Or is that not an option? – Johan Sep 12 '17 at 09:22
  • That isn't really an option. Also, these scripts selects a server based on some parameters and opens an ssh session to that server (or possibly servers in a tmux session), the scripts themselves don't depend on the TERM value. – Thayne Sep 13 '17 at 01:44
  • 2
    In that case you could include your bash profile, or a separate aliases script into the script with: shopt -s expand_aliases; source ~/.bash_aliases – Johan Sep 13 '17 at 08:07
10

On 2021-06-04, "allow ssh_config SetEnv to override $TERM" was committed to openssh-portable, which sounds like it will let you set SetEnv TERM in ~/.ssh/config, such as in a Host directive. (Or it will let you as soon as a release is cut with this patch, presumably.)

dsedivec
  • 326
  • 4
  • 7
  • Cool. This is the new correct answer. Just edit `~/.ssh/config` as long as you're running a post 2021-06-04 commit of ssh and sshd.... Great find! – erwin Sep 15 '21 at 08:55
10

man ssh:

     ssh reads ~/.ssh/environment, and adds lines of the format
     “VARNAME=value” to the environment if the file exists and users are
     allowed to change their environment.  For more information, see the
     PermitUserEnvironment option in sshd_config(5).

Edit:

Rats, I hoped it could be on the local side, still, if there's a will, there's a way. man ssh_conf:

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.

Depending on the configuration of sshd on the receiving end this may or may not fulfil the requirement of "no remote file modification".

Paweł Brodacki
  • 6,451
  • 19
  • 23
  • 1
    Yes, but this is configuration on remote side, and I need/want something that changes only on local end. –  Aug 17 '11 at 16:47
  • 5
    SendEnv is not related. It can *possibly* send additional env variables, but: 1. it cannot modify them, and 2. TERM is sent anyway, even if it's not listed in SendEnv. –  Aug 17 '11 at 19:52
9
TERM=vt100 ssh some.host.name

On remote, execute echo $TERM.

O G
  • 854
  • 4
  • 6
  • 2
    I though about it, but I want it set only for a subset of hosts I ssh to, so issuing TERM=... ssh all the time will not work. and remembering which hosts have old termcap info, and then changing command on the fly is not nice either. –  Aug 17 '11 at 16:48
  • Per-host configuration is supported only in /etc/ssh/ssh_config, however I know of no configuration value to support terminal schema mapping per host. – O G Aug 17 '11 at 16:53
  • It can also be done in ~/.ssh/config, which I know, but I also can't find any option to modify environment sent to remote server. Was hoping that I missed something. –  Aug 17 '11 at 17:03
6

Here's my quick and dirty solution I just threw together. I'd prefer something better. I guess I could use a shell script instead. Adjusting TERM values is left as an exercise to the reader.

# To move into a separate plugin...
function ssh {
   if [[ "${TERM}" = screen* || konsole* ]]; then
     env TERM=screen ssh "$@"
   else
     ssh "$@"
   fi
}

Ideally, it would do something like check the TERMs on the other side, using the ControlPersist stuff to prevent long delays for multiple connections.

docwhat
  • 202
  • 1
  • 3
  • 7
  • Thanks! I did something like this, but instead of checking for specific values of `$TERM` with an `if`/`else` construct, I'm using `$(echo -n "$TERM" | sed -e s/tmux/screen/)` to unconditionally replace the problematic "tmux" in my local term with the more universally accepted "screen" type ([source here](https://github.com/wincent/wincent/commit/ea0537ae47dcf0d4ba74b5c41915138c302b64e7)). – Greg Hurrell Dec 01 '15 at 20:20
  • @wincent `if` is preferred: you don't `fork` external processes. Keep our Planet green. – gavenkoa Jun 01 '21 at 09:13
  • even better than the `if` or `sed`: the [Shell Parameter Expansion](https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html#:~:text=%24%7Bparameter/pattern/string%7D) `${TERM/tmux/screen}` – clausavram Apr 26 '22 at 12:26