How do I make the apple terminal window auto change colour scheme when I ssh to a specific server

MacosTerminalOsx Leopard

Macos Problem Overview


When I ssh into a remote production server I would like the colour scheme of my terminal window to change to something brigh and scary, preferably red, to warn me that I am touching a live scary server.

How can I make it automatically detect that I have ssh'ed somewhere, and if that somewhere is on a specific list, change the colour scheme?

I want to update the Scheme of Terminal.app, not know how I would do this in a pure linux/unix env

Macos Solutions


Solution 1 - Macos

Put following script in ~/bin/ssh (ensure ~/bin/ is checked before /usr/bin/ in your PATH):

#!/bin/sh

HOSTNAME=`echo $@ | sed s/.*@//`

set_bg () {
  osascript -e "tell application \"Terminal\" to set background color of window 1 to $1"
}

on_exit () {
  set_bg "{0, 0, 0, 50000}"
}
trap on_exit EXIT

case $HOSTNAME in
  production1|production2|production3) set_bg "{45000, 0, 0, 50000}" ;;
  *) set_bg "{0, 45000, 0, 50000}" ;;
esac

/usr/bin/ssh "$@"

Remember to make the script executable by running chmod +x ~/bin/ssh

The script above extracts host name from line "username@host" (it assumes you login to remote hosts with "ssh user@host").

Then depending on host name it either sets red background (for production servers) or green background (for all other). As a result all your ssh windows will be with colored background.

I assume here your default background is black, so script reverts the background color back to black when you logout from remote server (see "trap on_exit").

Please, note however this script does not track chain of ssh logins from one host to another. As a result the background will be green in case you login to testing server first, then login to production from it.

Solution 2 - Macos

A lesser-known feature of Terminal is that you can set the name of a settings profile to a command name and it will select that profile when you create a new terminal via either Shell > New Command… or Shell > New Remote Connection….

For example, duplicate your default profile, name it “ssh” and set its background color to red. Then use New Command… to run ssh host.example.com.

It also matches on arguments, so you can have it choose different settings for different remote hosts, for example.

Solution 3 - Macos

Another solution is to set the colors strait in the ssh config file:

inside ~/.ssh/config

Host Server1
   HostName x.x.x.x
   User ubuntu
   IdentityFile ~/Desktop/keys/1.pem
   PermitLocalCommand yes
   LocalCommand osascript -e "tell application \"Terminal\" to set background color of window 1 to {27655, 0, 0, -16373}"

Host Server2
   HostName x.x.x.x
   User ubuntu
   IdentityFile ~/Desktop/keys/2.pem
   PermitLocalCommand yes
   LocalCommand osascript -e "tell application \"Terminal\" to set background color of window 1 to {37655, 0, 0, -16373}"

Solution 4 - Macos

Here's a combined solution based on a couple of existing answers that handles the exit. Also includes a little extra if you don't want to deal with 16 bit color values.

This should be put in your ~/.bash_profile

# Convert 8 bit r,g,b,a (0-255) to 16 bit r,g,b,a (0-65535)
# to set terminal background.
# r, g, b, a values default to 255
set_bg () {
    r=${1:-255}
    g=${2:-255}
    b=${3:-255}
    a=${4:-255}

    r=$(($r * 256 + $r))
    g=$(($g * 256 + $g))
    b=$(($b * 256 + $b))
    a=$(($a * 256 + $a))

    osascript -e "tell application \"Terminal\" to set background color of window 1 to {$r, $g, $b, $a}"
}

# Set terminal background based on hex rgba values
# r,g,b,a default to FF
set_bg_from_hex() {
    r=${1:-FF}
    g=${2:-FF}
    b=${3:-FF}
    a=${4:-FF}

    set_bg $((16#$r)) $((16#$g)) $((16#$b)) $((16#$s))
}

# Wrapping ssh command with extra functionality
ssh() {
    # If prod server of interest, change bg color
    if ...some check for server list
    then
        set_bg_from_hex 6A 05 0C
    end

    # Call original ssh command
    if command ssh "$@"
    then
        # on exit change back to your default
        set_bg_from_hex 24 34 52
    fi
}
  • set_bg - takes 4 (8 bit) color values
  • set_bg_from_hex - takes 4 hex values. most of my color references I use are in hex, so this just makes it easier for me. It could be taken a step further to actually parse #RRGGBB instead of RR GG BB, but it works well for me.
  • ssh - wrapping the default ssh command with whatever custom logic you want. The if statement is used to handle the exit to reset the background color.

Solution 5 - Macos

Combining answers 1 and 2 have the following:

Create ~/bin/ssh file as described in 1 with the following content:

#!/bin/sh
# https://stackoverflow.com/a/39489571/1024794
log(){
  echo "$*" >> /tmp/ssh.log
}
HOSTNAME=`echo $@ | sed s/.*@//`
log HOSTNAME=$HOSTNAME
# to avoid changing color for commands like `ssh user@host "some bash script"`
# and to avoid changing color for `git push` command:
if [ $# -gt 3 ] || [[ "$HOSTNAME" = *"git-receive-pack"* ]]; then
  /usr/bin/ssh "$@"
  exit $? 
fi

set_bg () {
  if [ "$1" != "Basic" ]; then
    trap on_exit EXIT;
  fi
  osascript ~/Dropbox/macCommands/StyleTerm.scpt "$1"
}

on_exit () {
  set_bg Basic
}


case $HOSTNAME in
  "178.222.333.44 -p 2222") set_bg "Homebrew" ;;
  "178.222.333.44 -p 22") set_bg "Ocean" ;;
  "192.168.214.111") set_bg "Novel" ;;
  *) set_bg "Grass" ;;
esac

/usr/bin/ssh "$@"

Make it executable: chmod +x ~/bin/ssh.

File ~/Dropbox/macCommands/StyleTerm.scpt has the following content:

#https://superuser.com/a/209920/195425
on run argv
  tell application "Terminal" to set current settings of selected tab of front window to first settings set whose name is (item 1 of argv)
end run

Words Basic, Homebrew, Ocean, Novel, Grass are from mac os terminal settings cmd,: terminal profiles

Solution 6 - Macos

You can set the $PS1 variable in your .bashrc.

red='\e[0;31m'
PS1="$\[${red}\]"

EDIT: To do this open the Terminal. Then say

#touch .bashrc

You can then open .bashrc in textEdit or in TextWrangler and add the previous commands.

Solution 7 - Macos

Set the terminal colours in the server's /.bashrc

I needed the same thing, something to make me aware that I was on a Staging or Production server and not in my Development environment, which can be very hard to tell, especially when in a Ruby console or something.

To accomplish this, I used the setterm command in my server's ~./bashrc file to inverse the colours of the terminal when connecting and restore the colours when exiting.

~/.bashrc
# Inverts console colours so that we know that we are in a remote server. 
# This is very important to avoid running commands on the server by accident.
setterm --inversescreen on

# This ensures we restore the console colours after exiting.
function restore_screen_colours {
  setterm --inversescreen off
}
trap restore_screen_colours EXIT

I then put this in all the servers' ~/.bashrc files so that I know when my terminal is on a remote server or not.

Another bonus is that any of your development or devops team get the benefit of this without making it part of the onboarding process.

Works great.

Solution 8 - Macos

Xterm-compatible Unix terminals have standard escape sequences for setting the background and foreground colors. I'm not sure if Terminal.app shares them; it should.

case $HOSTNAME in
    live1|live2|live3) echo -e '\e]11;1\a' ;;
    testing1|testing2) echo -e '\e]11;2\a' ;;
esac

The second number specifies the desired color. 0=default, 1=red, 2=green, etc. So this snippet, when put in a shared .bashrc, will give you a red background on live servers and a green background on testing ones. You should also add something like this to reset the background when you log out.

on_exit () {
    echo -e '\e]11;0\a'
}
trap on_exit EXIT

EDIT: Google turned up a way to set the background color using AppleScript. Obviously, this only works when run on the same machine as Terminal.app. You can work around that with a couple wrapper functions:

set_bg_color () {
    # color values are in '{R, G, B, A}' format, all 16-bit unsigned integers (0-65535)
    osascript -e "tell application \"Terminal\" to set background color of window 1 to $1"
}

sshl () {
    set_bg_color "{45000, 0, 0, 50000}"
    ssh "$@"
    set_bg_color "{0, 0, 0, 50000}"
}

You'd need to remember to run sshl instead of ssh when connecting to a live server. Another option is to write a wrapper function for ssh that scans its arguments for known live hostnames and sets the background accordingly.

Solution 9 - Macos

Why not just changing the shell prompt whenever you are logged in via SSH? There are usually specific shell variables: SSH_CLIENT, SSH_CONNECTION, SSH_TTY

Solution 10 - Macos

You should change the color of username and host machine name.

add the following line to your ~/.bash_profile file:

export PS1=" \[\033[34m\]\u@\h \[\033[33m\]\w\[\033[31m\]\[\033[00m\] $ "

The first part (purple colored) is what you're looking for.

Preview: enter image description here

This is my preferred colors. You can customize each part of prompt's color by changing m codes (e.g. 34m) which are ANSI color codes.

List of ANSI Color codes:

  • Black: 30m

  • Red: 31m

  • Green: 32m

  • Yellow: 33m

  • Blue: 34m

  • Purple: 35m

  • Cyan: 36m

  • White: 37m

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLaurie YoungView Question on Stackoverflow
Solution 1 - MacosYurii SoldakView Answer on Stackoverflow
Solution 2 - MacosChris PageView Answer on Stackoverflow
Solution 3 - Macosarnon cohenView Answer on Stackoverflow
Solution 4 - MacosbinglesView Answer on Stackoverflow
Solution 5 - MacosMaxim YefremovView Answer on Stackoverflow
Solution 6 - MacosMilhousView Answer on Stackoverflow
Solution 7 - MacosJoshua PinterView Answer on Stackoverflow
Solution 8 - MacosskymtView Answer on Stackoverflow
Solution 9 - MacosunexistView Answer on Stackoverflow
Solution 10 - MacosShayan AmaniView Answer on Stackoverflow