Files
CategoryResourceRepost/极客时间专栏/研发效率破局之道/个人效能/27 | 命令行:不只是酷,更重要的是能提高个人效能.md
louzefeng d3828a7aee mod
2024-07-11 05:50:32 +00:00

354 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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=&quot;\[\033[0m\]&quot; # unsets color to term's fg color
# regular colors
K=&quot;\[\033[0;30m\]&quot; # black
R=&quot;\[\033[0;31m\]&quot; # red
G=&quot;\[\033[0;32m\]&quot; # green
Y=&quot;\[\033[0;33m\]&quot; # yellow
B=&quot;\[\033[0;34m\]&quot; # blue
M=&quot;\[\033[0;35m\]&quot; # magenta
C=&quot;\[\033[0;36m\]&quot; # cyan
W=&quot;\[\033[0;37m\]&quot; # white
# empahsized (bolded) colors
MK=&quot;\[\033[1;30m\]&quot;
MR=&quot;\[\033[1;31m\]&quot;
MG=&quot;\[\033[1;32m\]&quot;
MY=&quot;\[\033[1;33m\]&quot;
MB=&quot;\[\033[1;34m\]&quot;
MM=&quot;\[\033[1;35m\]&quot;
MC=&quot;\[\033[1;36m\]&quot;
MW=&quot;\[\033[1;37m\]&quot;
# background colors
BGK=&quot;\[\033[40m\]&quot;
BGR=&quot;\[\033[41m\]&quot;
BGG=&quot;\[\033[42m\]&quot;
BGY=&quot;\[\033[43m\]&quot;
BGB=&quot;\[\033[44m\]&quot;
BGM=&quot;\[\033[45m\]&quot;
BGC=&quot;\[\033[46m\]&quot;
BGW=&quot;\[\033[47m\]&quot;
```
```
## 文件 $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 '&gt;' turns red
export PS1=&quot;\e[42m\t\e[m$N $W&quot;'$(__git_ps1 &quot;(%s) &quot;)'&quot;$N$PROMPT_COLOR\u@\H$N:$C\w$N\n\[&quot;'$CURSOR_COLOR'&quot;\]&gt;$W &quot;
export PROMPT_COMMAND='if [ $? -ne 0 ]; then CURSOR_COLOR=`echo -e &quot;\033[0;31m&quot;`; else CURSOR_COLOR=&quot;&quot;; 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=&quot;powerlevel9k/powerlevel9k&quot;
```
命令行提示符以外的其他配置主要是通过安装和使用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 &lt;theme&gt;
omf theme &lt;theme&gt;
## 我使用的是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@&lt;server-ip-or-name&gt;
```
下面这个录屏演示的是我日常工作中使用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的最大区别是什么是否有什么场景我们必须使用其中的一个吗
感谢你的收听,欢迎你在评论区给我留言分享你的观点,也欢迎你把这篇文章分享给更多的朋友一起阅读。我们下期再见!