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 $@ | sed s/.*@//`

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

/usr/bin/ssh "$@"

代码其实很好理解,通过读 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环境下工作(主要是我懒得搞

iTerm 主题与Badge跟随ssh变化

https://blog.dwx.io/iterm-theme-badge-on-demand/

Author

Jason

Posted on

14/10/19

Updated on

10/12/20

Licensed under

Comments

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×