mirror of
https://github.com/cheetahlou/CategoryResourceRepost.git
synced 2025-11-19 07:33:47 +08:00
354 lines
18 KiB
Markdown
354 lines
18 KiB
Markdown
<audio id="audio" title="27 | 命令行:不只是酷,更重要的是能提高个人效能" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/d3/4a/d305df11cd909f9146d06d90f8924d4a.mp3"></audio>
|
||
|
||
你好,我是葛俊。今天,我要与你分享的主题是,命令行下的高效工作技巧。
|
||
|
||
我先和你讲一个有意思的话题吧。命令行工具常常会给人一种黑客的感觉,好莱坞的电影里面常常出现命令行窗口的使用。不知道你听说过没有,很多好莱坞电影在拍摄时使用的其实是一个叫作[nmap](https://nmap.org)的工具。这个工具是做安全扫描的,只不过因为它的显示特别花哨,所以被很多电影采用。在nmap官方网站上,还专门列出来了这些电影的名单。
|
||
|
||
类似这种可以让自己看起来很忙的工具还有很多,比如[Genact](https://github.com/svenstaro/genact)。下面是一个使用Genact的录屏,当然这里的命令并没有真正运行。这可能是整个专栏中,唯一一个让你看起来效率很高,实际上却是降低效率的工具,但说不定对你有用,你懂的。
|
||
|
||
<img src="https://static001.geekbang.org/resource/image/2d/97/2dba0dfdd5f0260ad3b3082a7d3d2697.gif" alt="">
|
||
|
||
讲完这个娱乐性的话题,我们进入正题吧。
|
||
|
||
## 为什么要使用命令行?
|
||
|
||
GUI图形界面的出现是计算机技术的变革,极大方便了用户。但在这么多年后的今天,命令行工具为什么仍然有如此强大的生命力呢?
|
||
|
||
在我看来,对软件工程师来说,想要高效开发就必须掌握命令行,主要原因包括:
|
||
|
||
- 虽然鼠标的移动和点击比较直观,但要完成重复性的工作,使用键盘会快捷得多。这一点从超市的结算人员就可以看出来,使用键盘系统的收银员总是噼里啪啦地很快就可以完成结算,而使用鼠标点击的话明显慢很多。
|
||
- 作为开发人员,可以比较容易地使用命令行的脚本,对自己的工作进行自动化,以及和其他系统工具联动。但使用GUI的话,就会困难得多。
|
||
- 命令行通常可以暴露更完整的功能,让使用者对整个系统有更透彻的理解。Git就是一个典型的例子,再好的GUI Git系统都只能封装一部分Git命令行功能,要想真正了解Git,我们必须要使用命令行。
|
||
- 有一些情况是必须使用命令行的,比如SSH到远程服务器上工作的时候。
|
||
|
||
为了演示命令行的强大功能给我们带来的方便,下面是一个在本地查看文件并上传到服务器的流程的录屏。
|
||
|
||
<img src="https://static001.geekbang.org/resource/image/1d/29/1deb0006ea65cd5c4a28819a2cf50629.gif" alt="">
|
||
|
||
<img src="https://static001.geekbang.org/resource/image/95/40/958987c6594699ff1fb97b1622b21a40.gif" alt="">
|
||
|
||
通过这个案例,你可以看到命令行的以下几个功能:
|
||
|
||
- 在提示行会高亮显示时间、机器名、用户名、Git代码仓的分支和状态,以及上一个命令的完成状态。
|
||
- 输入命令的时候,高亮显示错误并自动纠错。
|
||
- 使用交互的形式进行文件夹的跳转,并方便查找文件,还可以直接在命令行里显示图片。
|
||
- 使用交互的工具,把文件上传到远端的服务器,并快速连接到远端查看传输是否成功。
|
||
|
||
整个流程全部都是在命令行里完成的,速度非常快,用户体验也非常好。正因为如此,我看到的硅谷特别高效的开发人员,绝大多数都大量使用命令行。那,面对成百上千的命令行工具,我们**怎样才能高效地学习和使用**呢?
|
||
|
||
我将高效学习使用命令行的过程,归纳为两大步:
|
||
|
||
1. 配置好环境;
|
||
1. 针对自己最常使用命令行的场景,有的放矢地选择工具。
|
||
|
||
今天,我就与你详细讲述**环境配置**这个话题。而关于选择工具的话题,我会在下一篇文章中与你详细介绍。总结来讲,环境配置主要包括以下四步:
|
||
|
||
1. 选择模拟终端;
|
||
1. 选择Shell;
|
||
1. 具体的Shell配置;
|
||
1. 远程SSH的处理。
|
||
|
||
这里需要注意的是,在命令行方面,macOS和Linux系统比Windows系统要强大许多,所以我主要以macOS和Linux系统来介绍,而关于Windows的环境配置,我只会捎带提一下。不过,macOS和Linux系统中的工具选择和配置思路,你可以借鉴到Windows系统中。
|
||
|
||
## 第一步,选择模拟终端
|
||
|
||
我将一个好的终端应该具有的特征,归纳为4个:
|
||
|
||
- 快,稳定;
|
||
- 支持多终端,比如可以方便地水平和纵向分屏,有tab等;
|
||
- 方便配置字体颜色等;
|
||
- 方便管理常用SSH的登录。
|
||
|
||
macOS系统自带的终端不太好用,常见的替代工具有iTerm2、Terminator、Hyper和Upterm。我平时使用的iTerm2,是一个免费软件,功能强大,具备上面提到的4个特征。下面我就以iTerm2为例展开介绍。其他几个工具上也有类似功能,所以你不必担心。
|
||
|
||
在多终端的场景方面,iTerm2支持多窗口、多标签页,同一窗口中可以进行多次水平和纵向分屏。这些操作以及窗口的跳转都有快捷键支持,你可以很方便地在网络上搜索到。
|
||
|
||
<img src="https://static001.geekbang.org/resource/image/d6/bf/d63c4054e8e23136da22b1d9d6e4c2bf.png" alt="">
|
||
|
||
在管理常用SSH的登录方面,iTerm2使用Profile(用户画像)来控制。比如,下面是一个连接到远程服务器案例的录屏。
|
||
|
||
可以看到,在我的工作环境里常会用到4个Profile,其中有两个是连接到远端服务器的,包括Mosh Remote Server 1和SSH Remote Server 2。工作时,我使用Cmd+O,然后选择Server 1这个Profile,就可以打开一个新窗口,连接到这个远程服务器上。
|
||
|
||
<img src="https://static001.geekbang.org/resource/image/ec/ae/ec60c3bf9bb2688ea59e76b1576078ae.gif" alt="">
|
||
|
||
每一个Profile都可以定义自己的字体、颜色、shell命令等。比如,Server 1是类生产服务器,我就把背景设置成了棕红色,提醒自己在这个机器上工作时一定要小心。所以在上面的录屏中你可以看到,连接到远端的SSH标签页,它的背景、标签页都是棕红色。另外,下面是如何对Profile颜色进行设置的截屏。
|
||
|
||
<img src="https://static001.geekbang.org/resource/image/54/58/54888d3d58612f9b557af6e45f40b758.png" alt="">
|
||
|
||
除了这些基础功能外,iTerm2还有很多贴心的设计。比如:
|
||
|
||
- **在屏幕中显示运行历史**(Cmd+Opt+B/F)。有些情况下,向上滚动终端并不能看到之前的历史,比如运行VIM或者Tmux的时候。这时,浏览显示历史就特别有用了。
|
||
- **高亮显示当前编辑位置**,包括高亮显示当前行(Cmd+Opt+;)高亮显示光标所在位置(Cmd+/)。
|
||
- **与上一次运行命令相关的操作**,包括显示上一次运行命令的地方(Cmd+Shift+up),选中上一个命令的输出(Cmd+Shift+A)。
|
||
|
||
其中第2、3项功能是由一组[macOS的集成工具](https://www.iterm2.com/documentation-utilities.html)提供的。这个工具集还包括显示图片的命令imgls、imgcat,显示自动补全命令,显示时间、注释,以及在主窗口旁显示额外信息等。这些设计虽然很小,但非常实用。
|
||
|
||
关于Windows系统,2019年5月微软推出了[Windows Terminal](https://devblogs.microsoft.com/commandline/introducing-windows-terminal/),支持多Tab,定制性很强,据说体验很不错。
|
||
|
||
选择好了终端,环境设置的第二步就是选择Shell。
|
||
|
||
## 第二步,选择Shell
|
||
|
||
在我看来,选择Shell主要有普遍性和易用性这两条原则。
|
||
|
||
Linux/Unix系统下,**Bash**最普遍、用户群最广,但是易用性不是很好。常用来替代Bash的工具有**Zsh**和**Fish**,它们的易用性都很好。下面是两张图片,用于展示Zsh和Fish在易用性方面的一些功能。
|
||
|
||
Zsh:
|
||
|
||
<img src="https://static001.geekbang.org/resource/image/31/a6/3198a7c972939d35de0c03bd26c4a8a6.gif" alt="">
|
||
|
||
Fish:
|
||
|
||
<img src="https://static001.geekbang.org/resource/image/08/32/082720f4dbe7e335a290938993d84732.gif" alt="">
|
||
|
||
我个人觉得Fish比Zsh更方便。事实上,Fish是Friendly Interactive Shell的简称。所以,交互是Fish的强项。可惜的是,Fish不严格遵循POSIX的语法,与Bash的脚本不兼容,而Zsh则兼容,所以我目前主要使用的是Zsh。
|
||
|
||
选好了模拟终端和Shell之后,便是配置环境的第三步,具体的Shell配置了。
|
||
|
||
## 第三步,具体的Shell配置
|
||
|
||
接下来,我以我自己使用的设置为例,向你介绍Bash、Zsh、Fish的具体配置吧。这里,主要包括**命令行提示符**的配置和其他配置两个方面。
|
||
|
||
之所以把命令行提示符单独提出来,是因为它一直展现在界面上,能提供很有用的价值,对命令行高效工作至关重要。下面是一张图片,展示了Bash、Zsh和Fish的命令行提示符。
|
||
|
||
<img src="https://static001.geekbang.org/resource/image/cd/bf/cd10736ba6a970f9a7f8d2703a4b45bf.png" alt="">
|
||
|
||
这个窗口分为三部分,最上面是Bash,中间是Zsh,最下面是Fish,都配置了文件路径、Git信息和时间戳等信息。接下来,我带你一起看看这3个工具应该如何配置吧。
|
||
|
||
**Bash比较麻烦,**配置文件包括定义颜色和命令行提示符的两部分:
|
||
|
||
```
|
||
## 文件 $HOME/.bash/term_colors,定义颜色
|
||
# Basic aliases for bash terminal colors
|
||
N="\[\033[0m\]" # unsets color to term's fg color
|
||
|
||
# regular colors
|
||
K="\[\033[0;30m\]" # black
|
||
R="\[\033[0;31m\]" # red
|
||
G="\[\033[0;32m\]" # green
|
||
Y="\[\033[0;33m\]" # yellow
|
||
B="\[\033[0;34m\]" # blue
|
||
M="\[\033[0;35m\]" # magenta
|
||
C="\[\033[0;36m\]" # cyan
|
||
W="\[\033[0;37m\]" # white
|
||
|
||
# empahsized (bolded) colors
|
||
MK="\[\033[1;30m\]"
|
||
MR="\[\033[1;31m\]"
|
||
MG="\[\033[1;32m\]"
|
||
MY="\[\033[1;33m\]"
|
||
MB="\[\033[1;34m\]"
|
||
MM="\[\033[1;35m\]"
|
||
MC="\[\033[1;36m\]"
|
||
MW="\[\033[1;37m\]"
|
||
|
||
# background colors
|
||
BGK="\[\033[40m\]"
|
||
BGR="\[\033[41m\]"
|
||
BGG="\[\033[42m\]"
|
||
BGY="\[\033[43m\]"
|
||
BGB="\[\033[44m\]"
|
||
BGM="\[\033[45m\]"
|
||
BGC="\[\033[46m\]"
|
||
BGW="\[\033[47m\]"
|
||
|
||
```
|
||
|
||
```
|
||
## 文件 $HOME/.bashrc,设置提示符及其解释
|
||
###### PROMPT ######
|
||
# Set up the prompt colors
|
||
source $HOME/.bash/term_colors
|
||
PROMPT_COLOR=$G
|
||
if [ ${UID} -eq 0 ]; then
|
||
PROMPT_COLOR=$R ### root is a red color prompt
|
||
fi
|
||
|
||
#t Some good thing about this prompt:
|
||
# (1) The time shows when each command was executed, when I get back to my terminal
|
||
# (2) Git information really important for git users
|
||
# (3) Prompt color is red if I'm root
|
||
# (4) The last part of the prompt can copy/paste directly into an SCP command
|
||
# (5) Color highlight out the current directory because it's important
|
||
# (6) The export PS1 is simple to understand!
|
||
# (7) If the prev command error codes, the prompt '>' turns red
|
||
export PS1="\e[42m\t\e[m$N $W"'$(__git_ps1 "(%s) ")'"$N$PROMPT_COLOR\u@\H$N:$C\w$N\n\["'$CURSOR_COLOR'"\]>$W "
|
||
export PROMPT_COMMAND='if [ $? -ne 0 ]; then CURSOR_COLOR=`echo -e "\033[0;31m"`; else CURSOR_COLOR=""; fi;'
|
||
|
||
```
|
||
|
||
命令行提示符之外的其他方面的配置,在Bash方面,我主要设置了一些命令行补全(completion)和别名设置(alias):
|
||
|
||
```
|
||
## git alias
|
||
alias g=git
|
||
alias gro='git r origin/master'
|
||
alias grio='git r -i origin/master'
|
||
alias gric='git r --continue'
|
||
alias gria='git r --abort'
|
||
|
||
|
||
## ls aliases
|
||
alias ls='ls -G'
|
||
alias la='ls -la'
|
||
alias ll='ls -l'
|
||
|
||
|
||
## git completion,请参考https://github.com/git/git/blob/master/contrib/completion/git-completion.bash
|
||
source ~/.git-completion.bash
|
||
|
||
```
|
||
|
||
**Zsh的配置就容易得多了,而且是模块化的**。基本上就是安装一个配置的框架,然后选择插件和主题即可。具体来说,我的Zsh命令行提示符配置步骤包括以下三步。
|
||
|
||
第一,[安装oh-my-zsh](https://github.com/robbyrussell/oh-my-zsh)。这是一个对Zsh进行配置的常用开源框架。
|
||
|
||
```
|
||
brew install zsh
|
||
|
||
```
|
||
|
||
第二,[安装powerline字体](http://powerline),供下一步使用。
|
||
|
||
```
|
||
brew install powerlevel9k
|
||
|
||
```
|
||
|
||
第三,在~/.zshrc中配置ZSH_THEME,指定使用powerlevel9k这个主题。
|
||
|
||
```
|
||
ZSH_THEME="powerlevel9k/powerlevel9k"
|
||
|
||
```
|
||
|
||
命令行提示符以外的其他配置,主要是通过安装和使用oh-my-zsh插件的方式来完成。下面是我使用的各种插件,供你参考。
|
||
|
||
```
|
||
## 文件~/.zshrc.sh 中关oh-my-zsh的插件列表,具体插件细节请参考https://github.com/robbyrussell/oh-my-zsh,以及使用Web搜索查询
|
||
plugins=(
|
||
git
|
||
z
|
||
vi-mode
|
||
zsh-syntax-highlighting
|
||
zsh-autosuggestions
|
||
osx
|
||
colored-man-pages
|
||
catimg
|
||
web-search
|
||
vscode
|
||
docker
|
||
docker-compose
|
||
copydir
|
||
copyfile
|
||
npm
|
||
yarn
|
||
extract
|
||
fzf-z
|
||
)
|
||
|
||
source $ZSH/oh-my-zsh.sh
|
||
|
||
```
|
||
|
||
**至于Fish的配置,和Zsh差不多,也是安装一个配置的框架,然后选择插件和主题即可。**在配置命令行提示符时,主要步骤包括以下两步。
|
||
|
||
第一,安装配置管理框架oh-my-fish:
|
||
|
||
```
|
||
curl -L https://get.oh-my.fish | fish
|
||
|
||
```
|
||
|
||
第二,查看、安装、使用oh-my-fish的某个主题,主题会自动配置好命令行提示符:
|
||
|
||
```
|
||
omf theme
|
||
omf install <theme>
|
||
omf theme <theme>
|
||
|
||
## 我使用的是bobthefish主题
|
||
omf theme bobthefish
|
||
|
||
```
|
||
|
||
这里有一篇不错的关于[使用oh-my-fish配置的文章](https://www.ostechnix.com/oh-fish-make-shell-beautiful/),供你参考。
|
||
|
||
Fish的其他方面的配置,也是使用oh-my-fish配置会比较方便。关于具体的配置方法,建议你参照[官方文档](https://github.com/oh-my-fish/oh-my-fish)。
|
||
|
||
关于环境的最后一个配置,是远程SSH的处理。
|
||
|
||
## 第四步,远程SSH的处理
|
||
|
||
SSH到其他机器,是开发人员的常见操作,最大的痛点是,怎样保持多次连接的持久性。也就是说,连接断开以后,远端的SSH进程被杀死,之前的工作记录、状态丢失,导致下一次连接进去需要重新设置,交易花销太大。有两类工具可以很好地解决这个问题。
|
||
|
||
**第一类工具是Tmux或者Screen**,这两个工具比较常见,用来管理一组窗口。
|
||
|
||
接下来,我以Tmux为例,与你描述其工作流程:首先SSH到远程服务器,然后用远程机器上的Tmux Client连接到已经运行的Tmux Session上。SSH断开之后,Tmux Client被杀死,但Tmux Session仍然保持运行,意味着命令的运行状态继续存在,下次SSH过去再使用Tmux Client连接即可。
|
||
|
||
如果你想深入了解Tmux的概念和搭建过程,可以参考[这篇文章](http://cenalulu.github.io/linux/tmux/)。
|
||
|
||
**第二类是一个保持连接不中断的工具,移动Shell**(Mobile Shell)。这也是我目前唯一见到的一个。这个工具是MIT做出来的,知道的人不多,是针对移动设备的网络经常断开设计的。
|
||
|
||
它的具体原理是,每次初始登录使用SSH,之后就不再使用SSH了,而是使用一个基于UDP的SSP协议,能够在网络断开重连的时候自动重新连接,所以从使用者的角度来看就像从来没有断开过一样。
|
||
|
||
接下来,**我以阿里云ECS主机、运行Ubuntu18.04为例,与你分享Mosh+Tumx的具体安装和设置方法。**
|
||
|
||
第一,服务器端安装并运行Mosh Server。
|
||
|
||
```
|
||
junge@iZ4i3zrhuhpdbhZ:~$ sudo apt-get install mosh
|
||
|
||
```
|
||
|
||
第二,打开服务器上的UDP端口60000~61000。
|
||
|
||
```
|
||
junge@iZ4i3zrhuhpdbhZ:~$ sudo ufw allow 60000:61000/udp
|
||
|
||
```
|
||
|
||
第三,在阿里云的Web界面上修改主机的安全组设置,允许UDP端口60000~61000。
|
||
|
||
<img src="https://static001.geekbang.org/resource/image/10/52/107e8927ab12b30699699db5ba54af52.jpg" alt="">
|
||
|
||
第四,在客户端(比如Mac上),安装Mosh Client。
|
||
|
||
```
|
||
jasonge@Juns-MacBook-Pro-2@l$ brew install mosh
|
||
|
||
```
|
||
|
||
第五,客户端使用Mosh,用与SSH一样的命令行连接到服务器。
|
||
|
||
```
|
||
jasonge@Juns-MacBook-Pro-2@l$ mosh junge@<server-ip-or-name>
|
||
|
||
```
|
||
|
||
下面这个录屏演示的是,我日常工作中使用Mosh + Tmux的流程。期间我会断开无线网,你可以看到Mosh自动连接上了,就好像来没有断过一样。
|
||
|
||
<img src="https://static001.geekbang.org/resource/image/9b/69/9beb7e70191ccd475d530aa4a5654a69.gif" alt="">
|
||
|
||
## 小结
|
||
|
||
今天,我与你分享的是使用命令行工具工作时,涉及的环境配置问题。
|
||
|
||
首先,我与你介绍了选择模拟终端、选择和配置Shell的重要准则,并结合案例给出了具体的工具和配置方法,其中涉及的工具包括iTerm2、Bash、Zsh、Fish等。然后,我结合远程SSH这一常见工作场景,给出了使用Tmux和Mosh的优化建议。
|
||
|
||
掌握了关于环境配置的这些内容以后,在下一篇文章中,我将与你介绍具体命令行工具的选择和使用。
|
||
|
||
其实,我推荐开发者多使用命令行工具,并不是因为它们看起来炫酷,而是它们确实可以帮助我们节省时间、提高个人的研发效能。而高效使用命令行工具的前提,是配置好环境。
|
||
|
||
以Mosh为例,我最近经常会使用iPad SSH到远端服务器做一些开发工作。在这种移动开发的场景下,iPad的网络经常断开,每次重新连接开销太大,基本上没办法工作。于是,我最终发现了Mosh,并针对开发场景进行了设置。现在,每次我重新打开iPad的终端时,远程连接自动恢复,好像网络从没有断开过一样。这样一来,我就可以在移动端高效地开发了。
|
||
|
||
而对研发团队来说,如果能够对命令行工作环境进行优化和统一,毫无疑问会节省个人选择和配置工具的时间,进而提升团队的研发效能。
|
||
|
||
## 思考题
|
||
|
||
你觉得Tmux和Screen的最大区别是什么?是否有什么场景,我们必须使用其中的一个吗?
|
||
|
||
感谢你的收听,欢迎你在评论区给我留言分享你的观点,也欢迎你把这篇文章分享给更多的朋友一起阅读。我们下期再见!
|
||
|
||
|