SSH and terminal background
Every once in a while there is some horror story happening about a dev-ops person executing commands on the wrong servers. These days I have control of a lot of servers which need attention and I often freak out when I'm inside mysql / mongo cli and perform operations, wondering if I'm on the machine that I think I am.
Recently I managed to spend some time on figuring out how can I improve my situation and here is what I came up with.
What is actually happening here is ssh executes a command on the local machine after successfully connecting to the server, which command changes the background of the terminal ( in my case iTerm ) and after the connection is closed ( the trickiest part ), another command is run which reverts the background to the default one.
Let's go step by step into the details :
- Change background ( iTerm )
- Change background ( Terminal )
- Configuring SSH's LocalCommand feature
- Final words and other methods
Change background ( iTerm )
This was quite trivial.
Create two additional copies of your default profile and name them e.g.
Staging
, Production
then change the background color of each of
them to what matches your default profile theme. The way to change the
profile of the current iTerm window for me was using
an escape code.
It looks like this :
$ echo -e "\033]50;SetProfile=Production\a"
To change it back your default profile you need to do the same, but just change the name :
$ echo -e "\033]50;SetProfile=NameOfYourDefaultProfile\a"
Change background ( Terminal )
For the macOS Terminal App this is done via AppleScript.
on run tbg
tell application "Terminal"
tell selected tab of front window
if (item 1 of tbg = "default") then
set background color to {9766, 12850, 14392}
else if (item 1 of tbg = "staging") then
set background color to {10280, 10280, 6425}
else if (item 1 of tbg = "production") then
set background color to {10794, 6682, 5911}
end if
end tell
end tell
end run
Just copy the file above and paste it into Script Editor, then save
it as ~/tbg.scpt
. Executing this script with argument default
,
production
or staging
will change the Terminal's background color.
$ osascript ~/tbg.scpt production
Since we won't use different profiles, but only background color change, you need to specify the background colors for your environments.
About that color format
The format is {R, G, B}
, but the colors are interpreted in
16bit values.
Credits goes to Stack Overflow's user @bingles.
To convert from 8bit to 16bit ( LOL ) I used this bash script.
#!/bin/bash
r=${1:-255}
g=${2:-255}
b=${3:-255}
r=$(($r * 256 + $r))
g=$(($g * 256 + $g))
b=$(($b * 256 + $b))
echo ${r} ${g} ${b}
So in order to get 16bit of pure green ( 0, 255, 0 )
you execute :
$ ./8to16rgb.sh 0 255 0
0 65535 0
You can use those colors for changing Terminal's background
Configuring SSH's LocalCommand feature
SSH support's LocalCommand feature, which executes a command when you connect to your server successfully. The problem comes when you need to also execute another command when you have disconnected.
After reading a bit I managed to achieve the effect via event handler that waits for the parent process to finish and executes a command when that happens.
Credits goes to Server Fault's user @wfaulk.
Based on the idea and the code of @wfaulk I managed to create a small C program phook, which basically executes a command when it starts and executes another one when the parent process has been terminated.
I also included a listener for catching SIGINT
system call in order to
make it work when SSH is terminated with CTRL+C
.
You can follow the instructions to install :
- Download the latest release of phook.
- Extract and run
make install
.
This should create /usr/local/bin/phook
executable that you will need
for SSH's LocalCommand.
With this program, configuring SSH is trivial. This is how my
~/.ssh/config
looks like :
#
# Hooks for certain hosts
#
Host do-styberry-staging do-mongo-01 do-mongo-02 do-mongo-arbiter
PermitLocalCommand yes
LocalCommand phook -e 'echo "\033]50;SetProfile=OceanicStaging\a"' -a 'echo "\033]50;SetProfile=Oceanic\a"'
Host do-styberry-production do-q-mongo-01 do-q-mongo-02 do-q-mongo-arbiter
PermitLocalCommand yes
LocalCommand phook -e 'echo "\033]50;SetProfile=OceanicProduction\a"' -a 'echo "\033]50;SetProfile=Oceanic\a"'
That's pretty much all of it.
Final words and other methods
Reading logs looks much better now.
There are of course other methods to achieve similar effect.
I don't want to go into details, but here are some issues that I had attempting to do the same with :
- Wrap
ssh
around a bash script. Adding/removing hosts will be difficult. Also it broke my autocomplete. - iTerm's automatic profile switching. Never managed to make it work properly. It actually needs you to install additional shell integrations and configuring hosts will be hard as well.