打造 10X Engineer Shell 工作環境

smalltown
Starbugs Weekly 星巴哥技術專欄
18 min readJun 9, 2020

Background

身為一位 SRE/DevOps 可能有一半的工作時間都必須跟 Shell 打交道,而一開始接觸 Linux 世界時,其實只知道 Bash 這個 Shell 而已,跟 GUI 操作相比起來,在 Bash 運用 CLI 來做事情,其實已經夠讓人興奮了,因為很多的操作行爲都來得有效率很多,例如一行簡單的指令 (~$ find ./ -name “terraform-repo”) 就可以在幾秒內找出想要找的檔案,但假如使用 GUI 的話,來回翻找的時間就不知道要花上多少了,更不用提還要耗費眼力,而且有時候可能漏看;那麼既然使用 Shell 工作的時間那麼多,正所謂工欲善其事必先利其器,有沒有什麼辦法可以讓我們使用它的時候更有效率而且還要可以符合目前的主流使用工具呢?沒錯,鋪梗鋪了這麼久,就是想要帶出今天要介紹的 Zsh 這套 Shell

Terminal

不過在開始把腳採進去 Shell 這個主題之前,先讓我提一下執行 Shell 的應用程式,相信很多使用 MacOS 的人都會用 iTerm 這套 Termaial 工具 (我自己也是),不過比較遺憾的地方在於,他並不能夠跨平台使用,他只存活於 MacOS 內而已 ;所以在這邊要推薦另外一個跨平台 Terminal 叫做 Hyper,因為其使用 Electron 打包,所以可以在 MacOS, Windows 與 Linux 平台上面使用,所以假如日常工作環境可能會涵括到多重平台,又想要達成使用體驗一致性的話,推薦可以試試看 Hyper,不過只能提到這邊了,因為此篇文章的重點主要會擺在 Shell 本身

Shell

Source: Linux command shells

年輕時候不懂事,以為 Shell = Bash 或是 Git = GitHub 😆水越踩越深之後才知道原來 Shell 是指用來跟 Linux Kernel 溝通的介面 (先承認自己恐龍本的內容都已經還給教授了 😭),其實相對古老而且普遍的 Shell 是 Sh (全名為 Bourne Shell),現在有些 Linux 系統 Root 帳號的預設 Shell 可能還是使用它,Bash 則是 Sh 的後繼相容與開源版本,他的名稱來自 Sh (Bourne Shell) 雙關語,意指 Bourne-Again SHell;目前在正式的 Server 端,這兩個 Shell 算是標配吧,那麼 ZshFish 跟這些老前輩的關係是什麼呢?

Zsh (Z Shell)

Zsh 是基於 Sh 之上,做出了大量的改進,並且同時加入了Bashkshtcsh的某些功能。

Fish (friendly interactive shell)

Fish 希望成為一個比其他 shell 互動性更強且體驗更佳的 shell,而他既不衍生於 Sh (Bourne Shell)也不衍生於 C Shell,所以按照人類社會的知識來看,他跟上面那堆並沒有親屬關係,可能可以算是外星人吧XD

就如上面所提到的,看來就是要在 Zsh 跟 Fish 中間選擇一套了,而因為自己的工作屬性關係 (SRE/DevOps),所以雖然是要在本地端使用,但還是希望一些開發的腳本或是指令在 Server 端運作的時候不會遇到不預期的錯誤,所以選擇了跟 Bash/Sh 基因比較相近的 Zsh,講古好像講太久了,先喝口水來動手操作一下 (底下安裝指令使用 MacOS 示範,其他平台的安裝可以參考線上文件)

# 檢查是否已經有安裝 Zsh (已經裝了的話,就可以跳過下一個安裝步驟)
~$ zsh --version
zsh 5.7.1 (x86_64-apple-darwin19.0)
# 假如電腦內沒有安裝 Zsh,可以利用下面的指令安裝
~$ brew install zsh

Configuration Framework

而 Zsh 之所以會強大,除了他從兄弟姐妹們那裡作出很多地改善之外,更厲害的地方在於它強大的社群與生態系,而為了要更方便地使用這些 Zsh Theme, Prompt, Plugins…等,便有了 Zsh 的組態管理工具

Oh My Zsh Framework

Oh My Zsh 應該算是老牌的 Zsh 組態管理框架,我一開始也是使用這套,用了好長一段時間也一直都很滿意,不過後來發現他的啟動速度好像被另外一套 Zim 比下去,所以這篇文章使用的 Framework 會是 Zim

Zim (Zsh IMproved FrameWork)

從上圖可以看出來 Zim 的啟動速度比 Oh My Zsh 快上一倍左右,常言道時間就是金錢,所以除非 Zim 有什麼地方無法滿足需求,不然建議可以使用看看

# 安裝 Zim
~$ curl -fsSL https://raw.githubusercontent.com/zimfw/install/master/install.zsh | zsh
) Git is installed.
) Using Zsh version 5.7.1
) ZIM_HOME not set, using the default one.
) Zsh is your default shell.
) Downloaded the Zim script to /Users/smalltown/.zim/zimfw.zsh
) Copied Zim template to /Users/smalltown/.zimrc
) Copied Zim template to /Users/smalltown/.zshrc
) Copied Zim template to /Users/smalltown/.zshenv
) Copied Zim template to /Users/smalltown/.zlogin
) Installed modules.
All done. Enjoy your Zsh IMproved! Restart your terminal for changes to take effect.
# 將 Zsh 設定成預設的 Shell (假如上面有提示 Zsh 還不是預設 Shell 的話)
~$ chsh -s $(which zsh)

把 Terminal 重新開啟之後,便安裝完成啦!接著我們便可以利用它來安裝其他好用的工具

Theme

而在 Theme 的選擇方面有兩個滿多人用的分別是 Powerlevel10k 以及 Spaceship,先澄清一下,看起來酷不酷炫並不是我考量的要點XD 我注重的是執行速度,命令自動完成,常用命令提示,跟 Prompt 資訊的完整性…等,其實 Prompt 就是那個 PS1 環境變數,預設顯示的資訊其實滿陽春的,通常就只有 1) 使用者名稱 2) Hostname 3) 當前資料夾,對於這個資訊爆炸的時代來說,其實很不夠用,例如,我想要知道目前的 Git 相關資訊 (目前位於哪一個 Branch, Commit 的狀況…等),或是想要知道 Kubernetes Context 目前使用得是哪一個,傳統的 PS1 的資訊其實完全不夠用,在 Prompt 顯示的資訊豐富程度來說,我覺得 Spaceship 很棒,而 Powerlevel10k 也不錯,不過在兩者的回饋速度來說,Powerlevel10k 略勝一籌,因此在經過一段時間的評估之後,我選擇了 Powerlevel10k (底下有實際比較影片供參考)

# 首先將 zmodule romkatv/powerlevel10k 加到 ~/.zimrc 中,~$ vim ~/.zimrc
...
zmodule romkatv/powerlevel10k
...
# 存檔完之後執行安裝指令
~$ zimfw install
) powerlevel10k: Installed
Done with install. Restart your terminal for any changes to take effect.

按照指示重開完 Terminal 之後便會進入 Powerlevel10k 的設定精靈頁面,在這邊會有滿多的步驟需要設定的,感覺有點像是在填問卷一樣,他會問使用者很多的問題,用以完成最適合自己使用習慣的環境

This is Powerlevel10k configuration wizard. You are seeing it because you
haven't defined any Powerlevel10k configuration options. It will ask you a few
questions and configure your prompt.
Install Meslo Nerd Font?(y) Yes (recommended).(n) No. Use the current font.(q) Quit and do nothing.

Kubernetes Context Management

目前 K8S 的維運模式應該都是朝向多個 Cluster 的方向在進行,也就是說會根據不同的環境 (開發,測試,生產) 甚至是不同功能性來切分成不同的 Cluster;但在這樣的前提之下,負責維運的人就會遇到必須要同時管理 N 個 Cluster 的情況,假如想要在 Terminal 中簡易地在不同 Cluster 和 Namespace 中切換的話,推薦 kubectx 這個工具,而其實他主要有兩個 Command 可供使用,分別是 kubectx 以及 kubens

# 安裝 kubectx (其他平台安裝方式)
~$ brew install kubectx

安裝完之後,首先在 terminal 輸入 kubectx 接著按下 tab 之後,因為有安裝 Powerlevel10k 的關係,便可以直接在左手邊看到目前位於哪一個 Cluster 跟 Namespace,下方也可以看到我們可以切換到哪一些 Cluster,接著輸入想要切換過去的 Cluster 名稱按下 Enter 後,就輕鬆切換成功嘍~

╭─ ~                                           ⎈ staging/kube-system
╰─❯ kubectx
development staging production

而假如在使用 kubectl 時不想要一直下 --namespace/-n 來指定 Namespace 的話,就可以透過 kubens 的幫忙,輸入 kubens 後按下 tab,就可以看到可供選擇的 Namespace,輸入完想要使用的 Namespace 按下 Enter 之後,使用 kubectl 所執行的指令就會都是針對該 Cluster 的指定 Namespace 來運作

╭─ ~                                           ⎈ staging/kube-system
╰─❯ kubens
default kube-system jenkins

kubectl 雖然好用,但是要查很多東西,一直下不同的指令也是很累XD 這時候就建議可以搭配 K9S 來使用,如此一來便可以在不同的 Pod 之間快速切換查找 Log

# 使用 brew 即可安裝 (其他平台安裝方式)
~$ brew install derailed/k9s/k9s
~$ k9s
Source k9s

AWS Profile Management

在組織內使用 AWS 的話,應該會切分成很多個不同的帳號,跟剛剛 Kubernetes Cluster 的狀況有點像,會根據開發環境還有功能性來切分,一個人要管十個帳號也是稀鬆平常的XD 這時候在 Terminal 下要一直切換 AWS Profile 其實是很累人的,好加在有一個好用而且可以加強安全的工具叫做 aws-vault

# 使用 brew 即可安裝 (其他平台安裝方式)
~$ brew cask install aws-vault

讓我們從他的 help Subcommand 來瞧瞧看他的能力有什麼,從說明裡面看出來 aws-vault 可以用來建立 aws-vault add 和查看 aws-vault list AWS Profile,而且就像他的名稱中有 Vault 一般,他會把 AK/SK 加密儲存起來,不會再讓他明碼的儲存在本地端的檔案中,並且透過 aws-vault exec 來達成使用不同的 AWS Profile 執行管理 AWS 資源的相關指令,關於如何使用 aws-vault 管理 AWS 多重帳號的更詳細資訊可以參考這篇文章 Infrastructure As Code Day 2 — Unity

~$ aws-vault help
usage: aws-vault [<flags>] <command> [<args> ...]
A vault for securely storing and accessing AWS credentials in development
environments.
Commands:
help [<command>...]
Show help.
add [<flags>] <profile>
Adds credentials, prompts if none provided
list [<flags>]
List profiles, along with their credentials and sessions
rotate [<flags>] <profile>
Rotates credentials
exec [<flags>] <profile> [<cmd>] [<args>...]
Executes a command with AWS credentials in the environment
remove [<flags>] <profile>
Removes credentials, including sessions
login [<flags>] <profile>
Generate a login link for the AWS Console

Version Management

用到的開發工具很多就算了,每一個工具一直發布新版本,不同的版本行爲還不一樣,這時候假如沒有辦法輕易的切換版本,就可能造成開發的效率低落,好加在有不少善心人士幫忙解決這方面的問題,底下列出一些自己常使用的本地端切換版本的好用工具

  • kubenvz: 管理 kubectl, kustomize, helm, helmfile 版本
  • tfenv: 管理 Terraform 版本
  • pyenv & pipenv: 管理 Python 版本

但可以發現每個工具都要裝一個實在是累死人了…但又不能不用,不然很難維護跨版本的專案,而這種情況在目前又是常態 ╮(╯_╰)╭ 不過…果然有分享有收穫,網友 Heng-Yi Wu 分享了 asdf 這個強大的通用版本管理工具,如此便可以把所有的版本管理一網打盡,底下列出簡單的用法,更多詳細的使用方式請參考官方文件

# 使用 brew 安裝即可 (其他平台安裝方式)
~$ brew install asdf
# 在 ~/.zshrc 加入以下的內容後,重新啟動 Terminal
#
# asdf
#
. $(brew --prefix asdf)/asdf.sh
# 安裝 kubectl plugin
~$ asdf plugin add kubectl
# 列入目前遠端有的 kubectl 版本
~$ asdf list all kubectl
...
# 挑兩個版本來安裝
~$ asdf install kubectl 1.16.10
~$ asdf install kubectl 1.18.3
# 列出本地端已經安裝的版本
~$ asdf list kubectl
1.16.10
1.18.3
# 設定想要使用的版本
~$ asdf global kubectl 1.18.3
# 查看目前 kubectl 是不是變成自己想要使用的版本了
~$ kubectl version
Client Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.3", GitCommit:"2e7996e3e2712684bc73f0dec0200d64eec7fe40", GitTreeState:"clean", BuildDate:"2020-05-20T12:52:00Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"darwin/amd64"}# 列出目前所有使用工具的版本
~$ asdf current
helm 3.2.3 (set by /Users/smalltown/.tool-versions)
kubectl 1.18.3 (set by /Users/smalltown/.tool-versions)
terraform 0.12.26 (set by /Users/smalltown/.tool-versions)
terragrunt 0.23.24 (set by /Users/smalltown/.tool-versions)

Misc (Optional)

Color LS

Source Color LS

到目前為止所推薦的東西都是用來增加工作效率的,來推薦一個令人賞心悅目,但卻會拖慢速度的功能XD 常常使用 Shell 的人,應該很習慣有事沒事就輸入 ls 看一下目前所在的路徑有什麼檔案吧,但在 Command Line 底下所顯示的檔案清單總是覺得有那麼一點點樸素,所以這邊來推薦一套叫做 Color LS 的工具 (在開始安裝之前,請先行安裝好 Ruby),稍微比較一下就可以發現列出檔案的速度會變慢一些,追求極速 Shell 體驗的人就不推薦安裝這個了;有興趣玩得更深入的話,可以看一下他在 GitHub 的說明文件,裡面有提到更多種顯示檔案的方式跟變換顏色等其他更進階的設定

# 使用 gem 安裝 Color LS
~$ gem install colorls
# 將底下的內容加到 ~/.zshrc 的結尾處
#
# color ls
#
source $(dirname $(gem which colorls))/tab_complete.sh
alias ls='colorls -h --group-directories-first'
alias l='colorls --group-directories-first --almost-all'
alias ll='colorls --group-directories-first --almost-all --long'

exa

Source exa

這邊要再推薦另外一個取代傳統 ls 的工具叫做 exa他沒有 Color LS 那麼樣的華麗,但在速度上就比較快一些,算是一個折衷的選擇方案,安裝方式很簡單,使用 brew 即可 (其他平台安裝方式),然後把本來一些慣用的 ls 指令 alias 成 exa 即可,最後當然不要忘記要把 Terminal 重新開啟讓它生效

# 使用 brew 即可安裝
~$ brew install exa
# 將底下的內容加到 ~/.zshrc 的結尾處,然後重新啟動 Terminal 即可
#
# exa
#
alias ls='exa'
alias l='exa -lbF --git'
alias ll='exa -lbGF --git'
alias llm='exa -lbGd --git --sort=modified'
alias la='exa -lbhHigUmuSa --time-style=long-iso --git --color-scale'
alias lx='exa -lbhHigUmuSa@ --time-style=long-iso --git --color-scale'
alias lS='exa -1'
alias lt='exa --tree --level=2'

bat

Source bat

cat 應該也是大家使用頻率很高的一個指令,bat 除了可以跟 cat 一樣顯示出檔案內容之外,他還多了 Syntax Highlighting 的功能,例如像上面的 htlm 檔案內容在顯示在 Terminal 下就變得十分的色彩繽紛

# 使用 brew 即可安裝 (其他平台安裝方式)
~$ brew install bat

tldr

Source tldr

man 指令三不五時也要用一下,畢盡不太可能把某個指令的詳細用法整個背下來,而 tldr 的功能跟 man 一樣可以列出指令的用法之外,還讓顯示的內容透過顏色更平易近人

# 透過 brew 安裝即可 (其他平台安裝方式)
~$ brew install tldr

Conclusion

雖然相關的文章已經有不少人寫了,但還是把自己完整測試過的組合分享出來,除了當成自己的個人紀錄,方便以後查找之外,搞不好也可以對遇到相同困擾的人有所助益;而此篇文章主要是以效能和功能性為主,所以就沒有提到怎麼調整字體或是顏色的相關主題,假如喜歡這篇文章的話,請幫我來個掌聲,要是有其他更棒的工具或是用法要推薦的話,歡迎留言在下方 ^^

P.S.

--

--

smalltown
Starbugs Weekly 星巴哥技術專欄

原來只是一介草 QA,但開始研究自動化維運雲端服務後,便一頭栽進 DevOps 的世界裏,熱愛鑽研各種可以提升雲端服務品質及增進團隊開發效率的開源技術