iTerm 主题与 Badge 跟随 ssh 变化

废话少说先上效果图

About

本文描述了在 macOS 的 iTerm 中,如何在 SSH 连接时自动修改终端主题和右上角 Badge。

Background

相信做运维的小伙伴或多或少会遇到过一些「靠谱」的公司,运维环境是有不同阶段的,包含 Production、Staging 和 Testing 等。甚至,管理不同阶段用的账户都有可能是分离的,但是大家可能更常遇到的问题是如何快速分辨出哪些机器是什么环境的。

Solve

我这边工作基本在 macOS 上完成,用的多的也就是 iTerm 了,至于为啥用 iTerm,那是因为自带的 Terminal 功能相对有限。

考虑到这些因素和自己准备实现的目标,我的方案是在 ssh 外面做个脚本,类似 wrapper 的实现,让 wrapper 告诉 iTerm 需要在何时改主题,这样就能解决不同环境下颜色对应变化的功能了,最后实现的成果就在上面的视频中。视频内,Staging 是蓝色,而 Production 则是很醒目的红色(意思就是让你别瞎鸡儿动嘛)

Wrapper 脚本

下面的脚本可以实现这个功能,具体内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/bin/bash

containsElement () {
local e match="$1"
shift
for e; do [[ "$e" == "$match" ]] && return 0; done
return 1
}

iterm2_set_user_var () {
printf "\033] 1337;SetUserVar=% s=% s\007" "$1" $(printf "% s" "$2" | base64 | tr -d '\n')
}

change_profile () {
NAME=$1; if [ -z "$NAME" ]; then NAME="$SSH_DEFAULT_THEME"; fi
echo -e "\033] 50;SetProfile=$NAME\a"
iterm2_set_user_var current_ssh_host "$HOSTNAME"
}

on_exit () {
change_profile
iterm2_set_user_var current_ssh_host "Jason's MacBook Pro"
}
trap on_exit EXIT

source ~/.aliases

HOSTNAME=`echo [email protected] | sed s/.*@//`

case $HOSTNAME in
nsys) change_profile "$SSH_DANGER_THEME" ;;
bhs) change_profile "$SSH_WARNING_THEME" ;;
esac

/usr/bin/ssh "[email protected]"

代码其实很好理解,通过读 HOSTNAME 来获得当前连接的主机名,然后按不同的主机名去对应不同的主题,使用 iTerm 集成的功能去修改当前主题,最后在退出时做个 trap 把退出消息捕获,方便把主题改回去。

脚本你放哪里都 ok,我是放在了 ~/.oh-my-zsh/helpers/ssh.sh 下。

Badge 配置

Badge 就是右上角那个暗红色的水印,相关文档 在这儿

默认主题里那个 Badge 内容,你可以在 第 22 行 修改。

上面设置的三个主题中,别忘了把 Badge 的内容改成 \(user.current_ssh_host),当然,后面那个 Edit 就是让你改样式的,你自己改改就行。

主题配置

然后你需要在 iTerm 的设置中,加几个主题,顺便把配色改了,当然改成啥样你随意……

别忘了最后一定要给你配置的这几个 Profile 起不同的名字,后面会用到。

比如我这边三个主题的名字就是下面这三个:

1
2
3
Dracula
Dracula_prod
Dracula_staging

接下来,在 ~/.aliases 里写好你刚刚准备好的三个 Profile:

1
2
3
export SSH_DEFAULT_THEME=Dracula
export SSH_DANGER_THEME=Dracula_prod
export SSH_WARNING_THEME=Dracula_staging

然后把你改好的脚本,做个 link,顺便加个可执行权限:

1
2
chmod +x ~/.oh-my-zsh/helper/ssh.sh
ln -s ~/.oh-my-zsh/helper/ssh.sh/usr/local/bin/ssh

最后开个新 Tab,试试效果就行。不出意外应该可以连接后变颜色了。

Advance

更高级的用法其实也有,下面提供几个思路

全自动查询类型

如果你的公司资产管理做的很不错,你可以试试调用资产查询接口去查你连的这个资产现在处于什么环境,然后根据返回去判断使用哪种类型的主题。
比如 aws 资产就可以通过在 aws 中台给资产加标签,然后用命令行工具去查询,搜索关键词后设置对应主题:

1
2
3
4
5
6
7
8
9
10
11
12
13
PRODUCTION_EC2_HOSTS=(`awslookup production '*' text | awk -F'\t' '{ print $2"\n"$3 }'`)
STAGING_EC2_HOSTS=(`awslookup staging '*' text | awk -F'\t' '{ print $2 }'`)

if containsElement "$HOSTNAME" "${PRODUCTION_EC2_HOSTS [@]}"; then
change_profile "$SSH_DANGER_THEME"
elif containsElement "$HOSTNAME" "${STAGING_EC2_HOSTS [@]}"; then
change_profile "$SSH_WARNING_THEME"
else
case $HOSTNAME in
*.other.com) change_profile "$SSH_DANGER_THEME" ;;
*.example.com) change_profile "$SSH_DANGER_THEME" ;;
esac
fi

在非 iTerm 里也用上这样的功能

那我就没啥时间折腾的,贴个 StackExchange 的帖子好了:

How to change terminal colors when connecting to SSH hosts

Troubleshoot

使用 Git 会报 Pipe 错误或者别的奇葩错误

之前我这份脚本是包含一些 Echo 的,因为这东西是 wrapper,所以一定要确保脚本只处理改主题的功能,不要输出任何东西,让他最后把输入重定向到真正的 ssh 上。

其他程序无法连接 ssh,报客户端问题

这类问题可以说是个汇总类型的问题,出现问题的本质是因为我们换了默认的 ssh,外面套了层 wrapper,所以很多程序在调用 ssh 的时候都会因为各种各样的问题,没法直接与 ssh 交互,甚至有很多程序是后台调用 ssh 的,根本用不到 iTerm。

所以对这类朋友,我有两种建议:

  1. 尝试去查阅对应客户端有没有设置 ssh 客户端路径的选项,把路径指向原来的 ssh 就可以。 macOS 里应该是 /usr/bin/ssh
  2. 尝试研究让这个脚本只在 iTerm 环境下工作(主要是我懒得搞
Author: Jason Cooper
Link: https://blog.dwx.io/iterm-theme-badge-on-demand/
Copyright Notice: All articles in this blog are licensed under BSD 3-Clause "New" or "Revised" License unless stating additionally.