11 | 研发环境:Facebook怎样让开发人员不再操心环境?-研发效率破局之道

今天,我来和你聊聊研发环境的问题,也就是如何才能让开发人员少操心环境,甚至不操心环境。从这篇文章开始,我们就一起进入工程方法模块了。

第 5 篇文章关于“持续开发”的讨论中,我与你介绍了获取开发环境是开发工作的核心步骤之一,对提高研发效能来说是非常值得优化的环节。当时,我与你提到了开发环境服务系统以及沙盒环境,解决了开发环境的准备工作。

而这里的“开发环境”只是研发环境的一部分,特指开发机器环境,包括开发机器的获取、网络配置、基本工具以及代码的获取和配置。今天,我们就来看看整体的研发环境的配置问题,从全局上切实解决开发人员因为操心环境而导致的效能低下。

在此之前,你可以先回忆下是否对以下问题似曾相识呢?

  • 开发人员使用的电脑配置太低,运行太慢,编译一次要 10 分钟;
  • 测试环境不够,上线时熬夜排队等环境;
  • 工具零散,不成系统,很多步骤需要手动操作,开发思路常常因为流程不连贯而被打断;
  • 团队成员的环境设置参差不齐,有个别开发人员环境配置得比较好,效率比较高,但没有固化下来,其他团队成员也用不上。

这些问题,实际上都可以归结为研发环境不够高效。就像低劣的空气质量和食物质量会影响我们的身体健康一样,不理想的研发环境会严重降低研发效能。

具体来说,按照开发流程,软件研发需要以下几种环境:

  • 开发机器;
  • IDE;
  • 开发过程中使用的各种工具、数据和配置;
  • 本地环境、联调环境;
  • 测试环境、类生产环境。

接下来,我会按照这个顺序,分别与你介绍这 5 套环境如何配置。

因为 Facebook 在环境配置上做得非常好,比如说,他们可以保证开发人员在 5 分钟之内拿到一套干净的开发机器环境。所以,我会与你着重分享 Facebook 的实践,然后根据这些实践,总结出一套提供高效研发环境的原则。同时,我也会与你介绍一些我在其他公司的落地实践,帮助你掌握与环境配置相关的内容。

如何配置高效的研发环境?

开发机器

Facebook 从不吝啬在开发机器上的投资。每个开发人员除了有一台笔记本外,还在远程数据中心有一台开发机器。数据中心的机器用于后端以及网站的开发,为方便描述,我称之为后端开发机。而笔记本有两个用处:一是用来做移动端 App 的开发;二是作为终端,连接到后端开发机做后端和网站开发。

两台机器的配置都非常强劲。后端开发机一开始是实体机器,后来为了便于管理和提高资源利用率,逐步转为了虚拟机,但不变的是配置依然强大。在 2015 年的时候,绝大部分机器配置都能达到 16 核 CPU 、144G 内存。笔记本有两种选择,一种是苹果 MacBook Pro,另一种是联想 ThinkPad,都是当时市场上顶配或者顶配下一级的配置。

开发机器的获取和释放,则是通过共享机器池以服务化自助化的方式完成的。更多细节,你可以再复习下第 5 篇文章的相关内容。

IDE

IDE,指的是集成开发环境。Facebook 持续在 IDE 上投入,以完善其功能、一致性及一体化体验。接下来,我会以后端和网站开发为例来说明。

因为代码存放并且运行在后端开发机上,所以在 2012 年以前,绝大部分开发人员都是使用 SSH 远程登录到后端开发机,在那里使用 VIM/Emacs 这类能在命令行里运行的编辑器进行开发工作。也有人尝试在笔记本上运行 GUI 的 IDE,远程挂载后端开发机上的文件系统,但总是有卡顿,效果不好。

在这种情况下,公司首先采用的办法是,尽量提高命令行编辑器的体验,把 VIM/Emacs 配置成类似 IDE 的工具,将最常见的功能,比如代码搜索、代码跳转、Debugger 等集成进去,效果还算可以。

不过,与 GUI 形式的 IDE 相比,这种命令行的工作方式还是有一些局限性,比如,和其他工具服务集成不方便,需要记忆大量快捷键,在显示形式上不够丰富导致用户体验不够好,等等。所以,Facebook 持续投入研究 GUI 形式的 IDE。

第一个成型的 GUI IDE 是一个 Web IDE,也就是在数据中心运行一些 Web IDE 服务。这些 IDE 服务连接到开发者的后端开发机上获取代码,同时提供网页界面,供开发人员用浏览器登录,进行开发工作。这种专门的 IDE 服务解决了远程文件夹挂载的卡顿问题,同时跟其他服务集成起来也很方便。

比如,它可以与 Phabricator 的代码审查功能集成在一起,在代码中用 inline 的方式显示其他人对你的代码的 comments,也就是说,在两行代码之间显示一个额外区域,用于展示 comments。类似的,它还可以方便地与代码搜索服务、代码跳转服务、Debugger 集成,甚至还可以跟 CI/CD 工具链的发布工具集成,所以非常方便。

到 2014 年的时候,Facebook 的大部分开发人员都逐渐转移到这个 Web IDE 上去了。如果你想深入了解 Web IDE,可以参考下Apache Che项目。

这个 Web IDE 已经很方便了,但基于网页的 IDE 在易用性和安全性还是有一些局限,所以 Facebook 继续加大在 GUI 形式的 IDE 方面的投入,最后使用 Electron 框架实现了一个原生的 IDE,也就是Nuclide

Nuclide 的工作原理和 Web IDE 基本一致,都是在数据中心运行 IDE 服务,IDE 的前端则运行在本地笔记本上,通过与 IDE 服务联通实现代码编辑等功能。只不过 Nuclide 的前端,是运行在开发者笔记本上的一个原生应用,而 Web IDE 的前端是运行在笔记本上的网页浏览器而已。Nuclide 的功能比 Web IDE 更强大,易用性也更好,同时因为没有浏览器的依赖,安全性也更好一些。

本地环境、联调环境

关于 Facebook 的本地环境,我已经在第 5 篇文章中介绍过了,主要就是加快本地构建,使用生产环境的数据,从而使得本地环境更加快捷、方便。

而至于联调环境,我曾在第 6 篇文章中简单提过。在代码提交到 Phabricator 上进行审查的时候,Phabricator 会调用一个沙盒系统创造出一个沙盒环境,运行正在被审查的代码。这个系统也是用机器池实现的,同时也是一个自助式服务,也就是说开发人员可以不通过 Phabricator,直接调用 API 来生成沙盒环境。

本地环境和联调环境是开发中最高频使用的环境,对持续开发很重要。接下来,我再与你分享两个我在其他公司的实施案例吧。

第一个例子是,我在 Stand 公司搭建本地环境。Stand 的业务规模小,因此并没有使用微服务,主要的服务只有单体的网站后端服务、数据库服务 MySQL、缓存服务 Redis,以及一些数据监控服务,相对来说比较简单。

我们的做法是,把这些依赖服务尽量在本地开发机器(也就是笔记本)上都运行一个实例。实在不能在本地运行的服务,要么在本地环境运行时不调用它,要么就在调用它的时候传递额外的参数,表明这个调用来自开发环境,而被调用的服务则针对这样的调用进行特殊处理,从而达到不污染线上环境的效果。

这是一个很常见的办法,简单有效。不过,它的缺点是本地环境数据跟线上环境有区别。

如果你的系统采用的是微服务,则可以采用以下 3 种常见办法。

  • 第一种方法是,直接在自己的机器上把所有的依赖服务都跑起来。这种方法的优点是方便,但要求开发机器配置要求高。
  • 第二种方法是,团队维护一个环境,让大家的开发环境接入。也就是,开发者自己的机器上只运行自己开发的服务,调用其他服务时就使用这个共享环境中运行的服务实例。这种方式对开发机器要求不高,但需要团队维护一个环境,并且一般来说大家需要经常更新这个环境中的服务,整个环境容易不稳定。
  • 第三种方法是,使用服务虚拟化工具,来模拟依赖的服务,比如MountbankWireMock。你可以参考篇文章来了解 WireMock 的使用方法。

第二个例子是,我为一个云产品团队提供联调环境。这个云产品结构非常复杂,有十多个服务,至少需要 3 台服务器;不但有软件,还有数据、组网等复杂的设置,部署很困难;更严重的问题是,这个环境一旦损坏就很难修复,需要从头再来,所以开发人员自己配置基本不可能,运维人员也是忙于维护,应接不暇。

针对这个问题,我们也是使用了机器池的办法。不过,这个机器池里面的单元不再是单个机器,而是由 3 台机器组成的服务。这个服务自助化提供给开发者使用,使用之后自动回收销毁。

同时,确保机器池中有两套空闲环境。不够就补充,多了就删除,以保证获取环境时可以马上得到,同时又不会因为有太多空闲环境而造成资源浪费。

另外,每次有了新的稳定版本,运维人员都会更新脚本,并重新安装和配置系统,保证开发人员能够在稳定版本上进行联调。

这样一来,就解决了团队开发人员的环境问题,将获取环境的时间由 2~4 个小时缩短到了几分钟。

开发过程中使用的各种工具、数据和配置

除了 IDE,开发过程中还会用到其他工具,比如代码搜索、发布部署,以及日志查看工具等。这些工具的组合,可能与你平时理解的开发环境不大一样,但事实上它也是一种广义的开发环境,对开发效率影响很大。

这部分环境的优化,主要是使用工具之间的网状互联来提高效率。关于工具的网状互联,我在第 4 篇文章中有介绍。这里,我想强调 Facebook 在的另一个重要实践:重视开发体验,将开发流程中常用步骤的自动化做到极致

我用一个具体的例子来说明。我们都知道,Git 的 Commit Message(代码提交描述)是提供信息的重要渠道。但它有一个局限,就是只能存储文本,而图片在描述问题时常常比文字有效得多,也就是“A picture is worth a thousand words”,翻译为中文就是我们常说的“一图胜千言”。

为解决这个问题,Facebook 采用了以下方式:

  1. 提供了一个图片存储服务,并为上传的图片提供永久 URL;
  2. 开发了一个端测的截屏工具,截屏之后自动上传到图片存储服务,而且,在上传成功之后自动把图片 URL 保存到本地笔记本的系统剪贴板中;
  3. 提供了一个内部使用的 URL 缩短工具,避免 URL 太长占用太多文字空间。

这三个工具集成起来,一个具体的使用场景是这样的:我在写 Commit Message 的时候,如果要截屏描述修改效果,就使用一个快捷键(比如 Cmd+Alt+4)激活截屏工具,随后拖动鼠标截屏,然后使用 Cmd+v 就可以直接把图片的 URL 粘贴到 Commit Message 里面了。

这个工作流非常顺畅、高效,不仅被大量用于 Commit Message 的书写中,也被经常被用在聊天工具中。后来,我到了其他公司,都会先配置这样一套工具流程。

测试环境、类生产环境

在测试环境、类生产环境的管理上,Facebook 使用一个叫作TupperWare的内部系统,以 IaC 的方式进行管理。不过,Facebook 并没有开源这个系统。如果你所在公司使用的是 Docker,那可以使用 Kubernetes 实现类似的功能。

如果你们没有使用 Docker,可以试试 HashiCorp 公司的Terraform,或者使用AnsibleChef之类的配置管理工具,来产生一套干净的环境供团队成员使用,之后再销毁,既方便又不浪费资源。

这里,我再与你分享一个我在Stand 公司使用 AWS 管理压测环境的例子。当时我们没有使用 Docker,于是,我们选择了 AWS 的 OpsWorks 框架。它是 AWS 基于 Chef-Solo 开发的一个应用程序管理解决方案,同时支持基础设施的建模和管理。

OpsWorks 这个框架的用法也是声明式的,只不过这个声明不是纯代码,而是在 AWS 的网页上配置的,使用效果和 TupperWare 差不多,就是首先定义一个压测环境需要几台机器,需要运行什么操作系统、需要什么负载均衡器、需要什么数据库等。

然后,通过 OpsWorks 上暴露的钩子,使用代码来管理应用的生命周期,从而实现系统和应用的初始化。通过这种方式,我们可以很方便地使用 OpsWorks 产生一个云主机集群用于压测,结束之后马上删除,方便而且划算。

其实,使用 Ansible 或者 Chef 也可以实现类似功能,但需要自己开发些东西,这里我就不详细讨论了。

提供高效研发环境的原则

通过以上实践可以看出,配置高效的研发环境主要包括以下几条原则:

  1. 舍得投入资源,用资源换取开发人员时间。Facebook 之所以从不吝啬在开发机器硬件上的投入,是因为人力成本更高。
  2. 对环境的获取进行服务化、自助化。这一点可以在开发机器、联调环境的获取上,得到很好的体现。同时常常使用 IaC、配置管理系统(比如 Chef)和机器池的方法来实现,同时利用弹性伸缩来节约资源。
  3. 注重环境的一体化、一致性,也就是要把团队的最佳实践固化下来。比如 Facebook 一个常见的操作是,配置文件统一处理。以 VIM 为例,将 VIM 的配置文件存放到网络共享文件夹中,开发人员只要在自己的.bashrc 文件中加上一行
 
source /home/devtools/vimconfig
 

就可以搞定。

小结

今天,我首先按照开发流程,也就是开发机器、IDE、本地环境和联调环境、开发过程中使用的各种工具及配置,以及测试环境和类生产环境的顺序,与你讲述了高效研发环境的具体实践。然后,基于这些实践,总结了 3 个基本原则:一是,用资源换时间;二是,服务化、自助化环境的获取;三是,实现环境的一体化、一致性。

我觉得,这些原则和实践的背后有一个重要思路,就是 Facebook 重视环境,并持续优化环境。这一点在 IDE 的演化上尤为明显,从命令行到 Web IDE 再到 Nuclide,一直在进步。另外,在去年年底,Facebook 停止了对 Nuclide 的开源项目的维护,这也意味着后面他们可能还会有对 IDE 的一轮新的优化。

以上种种做法,使得我在 Facebook 做开发的时候,对研发环境的感觉就是不用操心,需要使用的时候直接到网站上申请就可以使用;配置也方便,团队的配置都已经在那里了;同时,环境中的各种工具、流程都很顺畅,让我能够静下心来做开发、写算法,做我最能提供价值的事情。

image

https://github.com/svenstaro/genact

https://nmap.org/movies/

为什么要使用命令行?

GUI 图形界面的出现是计算机技术的变革,极大方便了用户。但在这么多年后的今天,命令行工具为什么仍然有如此强大的生命力呢?
在我看来,对软件工程师来说,想要高效开发就必须掌握命令行,主要原因包括:
虽然鼠标的移动和点击比较直观,但要完成重复性的工作,使用键盘会快捷得多。这一点从超市的结算人员就可以看出来,使用键盘系统的收银员总是噼里啪啦地很快就可以完成结算,而使用鼠标点击的话明显慢很多。
作为开发人员,可以比较容易地使用命令行的脚本,对自己的工作进行自动化,以及和其他系统工具联动。但使用 GUI 的话,就会困难得多。
命令行通常可以暴露更完整的功能,让使用者对整个系统有更透彻的理解。Git 就是一个典型的例子,再好的 GUI Git 系统都只能封装一部分 Git 命令行功能,要想真正了解 Git,我们必须要使用命令行。
有一些情况是必须使用命令行的,比如 SSH 到远程服务器上工作的时候。
为了演示命令行的强大功能给我们带来的方便,下面是一个在本地查看文件并上传到服务器的流程的录屏。
通过这个案例,你可以看到命令行的以下几个功能:
在提示行会高亮显示时间、机器名、用户名、Git 代码仓的分支和状态,以及上一个命令的完成状态。
输入命令的时候,高亮显示错误并自动纠错。
使用交互的形式进行文件夹的跳转,并方便查找文件,还可以直接在命令行里显示图片。
使用交互的工具,把文件上传到远端的服务器,并快速连接到远端查看传输是否成功。
整个流程全部都是在命令行里完成的,速度非常快,用户体验也非常好。正因为如此,我看到的硅谷特别高效的开发人员,绝大多数都大量使用命令行。那,面对成百上千的命令行工具,我们怎样才能高效地学习和使用呢?
我将高效学习使用命令行的过程,归纳为两大步:
 
配置好环境;
 
针对自己最常使用命令行的场景,有的放矢地选择工具。
今天,我就与你详细讲述环境配置这个话题。而关于选择工具的话题,我会在下一篇文章中与你详细介绍。总结来讲,环境配置主要包括以下四步:
 
选择模拟终端;
 
选择 Shell;
 
具体的 Shell 配置;
 
远程 SSH 的处理。
这里需要注意的是,在命令行方面,macOS 和 Linux 系统比 Windows 系统要强大许多,所以我主要以 macOS 和 Linux 系统来介绍,而关于 Windows 的环境配置,我只会捎带提一下。不过,macOS 和 Linux 系统中的工具选择和配置思路,你可以借鉴到 Windows 系统中。

第一步,选择模拟终端

我将一个好的终端应该具有的特征,归纳为 4 个:
快,稳定;
支持多终端,比如可以方便地水平和纵向分屏,有 tab 等;
方便配置字体颜色等;
方便管理常用 SSH 的登录。
macOS 系统自带的终端不太好用,常见的替代工具有 iTerm2、Terminator、Hyper 和 Upterm。我平时使用的 iTerm2,是一个免费软件,功能强大,具备上面提到的 4 个特征。下面我就以 iTerm2 为例展开介绍。其他几个工具上也有类似功能,所以你不必担心。
在多终端的场景方面,iTerm2 支持多窗口、多标签页,同一窗口中可以进行多次水平和纵向分屏。这些操作以及窗口的跳转都有快捷键支持,你可以很方便地在网络上搜索到。
在管理常用 SSH 的登录方面,iTerm2 使用 Profile(用户画像)来控制。比如,下面是一个连接到远程服务器案例的录屏。
可以看到,在我的工作环境里常会用到 4 个 Profile,其中有两个是连接到远端服务器的,包括 Mosh Remote Server 1 和 SSH Remote Server 2。工作时,我使用 Cmd+O,然后选择 Server 1 这个 Profile,就可以打开一个新窗口,连接到这个远程服务器上。
每一个 Profile 都可以定义自己的字体、颜色、shell 命令等。比如,Server 1 是类生产服务器,我就把背景设置成了棕红色,提醒自己在这个机器上工作时一定要小心。所以在上面的录屏中你可以看到,连接到远端的 SSH 标签页,它的背景、标签页都是棕红色。另外,下面是如何对 Profile 颜色进行设置的截屏。
除了这些基础功能外,iTerm2 还有很多贴心的设计。比如:
在屏幕中显示运行历史(Cmd+Opt+B/F)。有些情况下,向上滚动终端并不能看到之前的历史,比如运行 VIM 或者 Tmux 的时候。这时,浏览显示历史就特别有用了。
高亮显示当前编辑位置,包括高亮显示当前行(Cmd+Opt+;)高亮显示光标所在位置(Cmd+/)。
与上一次运行命令相关的操作,包括显示上一次运行命令的地方(Cmd+Shift+up),选中上一个命令的输出(Cmd+Shift+A)。
其中第 2、3 项功能是由一组macOS 的集成工具提供的。这个工具集还包括显示图片的命令 imgls、imgcat,显示自动补全命令,显示时间、注释,以及在主窗口旁显示额外信息等。这些设计虽然很小,但非常实用。
关于 Windows 系统,2019 年 5 月微软推出了Windows Terminal,支持多 Tab,定制性很强,据说体验很不错。
选择好了终端,环境设置的第二步就是选择 Shell。

第二步,选择 Shell

在我看来,选择 Shell 主要有普遍性和易用性这两条原则。
Linux/Unix 系统下,Bash最普遍、用户群最广,但是易用性不是很好。常用来替代 Bash 的工具有ZshFish,它们的易用性都很好。下面是两张图片,用于展示 Zsh 和 Fish 在易用性方面的一些功能。
Zsh:
Fish:
我个人觉得 Fish 比 Zsh 更方便。事实上,Fish 是 Friendly Interactive Shell 的简称。所以,交互是 Fish 的强项。可惜的是,Fish 不严格遵循 POSIX 的语法,与 Bash 的脚本不兼容,而 Zsh 则兼容,所以我目前主要使用的是 Zsh。
选好了模拟终端和 Shell 之后,便是配置环境的第三步,具体的 Shell 配置了。

第三步,具体的 Shell 配置

接下来,我以我自己使用的设置为例,向你介绍 Bash、Zsh、Fish 的具体配置吧。这里,主要包括命令行提示符的配置和其他配置两个方面。
之所以把命令行提示符单独提出来,是因为它一直展现在界面上,能提供很有用的价值,对命令行高效工作至关重要。下面是一张图片,展示了 Bash、Zsh 和 Fish 的命令行提示符。
这个窗口分为三部分,最上面是 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。这是一个对 Zsh 进行配置的常用开源框架。
 
 
brew install zsh
第二,安装 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 配置的文章,供你参考。
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 的概念和搭建过程,可以参考这篇文章
第二类是一个保持连接不中断的工具,移动 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。
第四,在客户端(比如 Mac 上),安装 Mosh Client。
 
 
jasonge@Juns-MacBook-Pro-2@l$ brew isntall mosh
 
第五,客户端使用 Mosh,用与 SSH 一样的命令行连接到服务器。
 
 
jasonge@Juns-MacBook-Pro-2@l$ mosh junge@<server-ip-or-name>
 
下面这个录屏演示的是,我日常工作中使用 Mosh + Tmux 的流程。期间我会断开无线网,你可以看到 Mosh 自动连接上了,就好像来没有断过一样。

小结

今天,我与你分享的是使用命令行工具工作时,涉及的环境配置问题。
首先,我与你介绍了选择模拟终端、选择和配置 Shell 的重要准则,并结合案例给出了具体的工具和配置方法,其中涉及的工具包括 iTerm2、Bash、Zsh、Fish 等。然后,我结合远程 SSH 这一常见工作场景,给出了使用 Tmux 和 Mosh 的优化建议。
掌握了关于环境配置的这些内容以后,在下一篇文章中,我将与你介绍具体命令行工具的选择和使用。
其实,我推荐开发者多使用命令行工具,并不是因为它们看起来炫酷,而是它们确实可以帮助我们节省时间、提高个人的研发效能。而高效使用命令行工具的前提,是配置好环境。
以 Mosh 为例,我最近经常会使用 iPad SSH 到远端服务器做一些开发工作。在这种移动开发的场景下,iPad 的网络经常断开,每次重新连接开销太大,基本上没办法工作。于是,我最终发现了 Mosh,并针对开发场景进行了设置。现在,每次我重新打开 iPad 的终端时,远程连接自动恢复,好像网络从没有断开过一样。这样一来,我就可以在移动端高效地开发了。
而对研发团队来说,如果能够对命令行工作环境进行优化和统一,毫无疑问会节省个人选择和配置工具的时间,进而提升团队的研发效能。
 

Tmux - Linux 从业者必备利器

本文详细介绍tmux的概念和搭建流程

文章欢迎转载,但转载时请保留本段文字,并放置文章的顶部 作者:卢钧轶(cenalulu) 本文原文地址:http://cenalulu.github.io/linux/tmux/

tmux

为什么使用tmux

tmux是什么?tmux是linux中的一个管理窗口的程序。那么问题来了:Mac自带的Iterm2很好用啊。既支持多标签,也支持表格内部面板的分割,为什么还要用tmux?其实,多标签和分割表格只是tmux的部分功能。用tmux的主要是提供了一个表格组合存储和恢复的功能。看看以下的使用场景是否适合你:

  • 公司台式机上开了许多vim和log打印窗口下班了。到家后灵感突发,想要继续编码,登陆VPN,SSH连上台式机后发现又要重新打开各种窗口,瞬间没心情了。。。FML!这个时候你就在你的公司台式机上装个tmux。同组工作环境,在多处共享。
  • 公司服务器上调试程序,开了多个窗口。出去吃了个饭,发现SSH超时了,broken pipe。重头开始。。。FML!如果你之前用过tmux就不会出现这样的问题,attach就能找回原来打开的那些窗口。

tmux的基本概念

我们先来理解tmux的几个元素。tmux的主要元素分为三层:

  • 会话的一组窗口的集合,通常用于百年之间同一个任务。会话可以有自己的名字作为任务的切换。
  • Window单个可视窗口。Windows有自己的编号,也可以认为和ITerm2中的Tab类似。
  • 窗格一样,被划分成小块的窗口,相当于Vim中 Cw +v 后的效果。

为了更好的理解,下面是三个元素在 tmux 中的具体执行。

概念

可以看到Session总在tmux的左下角显示,通常会为他命名。比如我正在写博客,打开了很多窗口那么我就会把这组窗口命名为blog方便之后的重连和切换。而窗口也在最下方以一个Tab的形式进行显示。每个窗口都有自己的需要,也以当前活动进程的名字命名。而Pane就比较好理解,即把单个块窗口分割成多个小后面的元素。


安装

这里以Mac环境为例。Linux的方法类似Centos系列的可以使用yum install tmux安装。

brew install tmux

安装完成直接执行tmux可能会有以下报错,按照下面的步骤执行命令即可

$junyilu> tmux
dyld: Library not loaded: /usr/local/lib/libevent-2.0.5.dylib
Referenced from: /usr/local/Cellar/tmux/1.9a/bin/tmux
Reason: image not found
Trace/BPT trap: 5

$junyilu> brew link libevent
Linking /usr/local/Cellar/libevent/2.0.22...
Error: Could not symlink lib/pkgconfig/libevent.pc
/usr/local/lib/pkgconfig is not writable.

$junyilu> sudo chown junyilu /usr/local/lib/pkgconfig

$junyilu> brew link libevent
Linking /usr/local/Cellar/libevent/2.0.22... 25 symlinks created

tmux的基本操作

Prefix-Command前置操作:所有下面介绍的快捷键,都必须以前置操作开始。tmux默认的前置操作是CTRL+b。例如,想要我们新建一个表单,就需要先在键盘的上摁下CTRL+b,读取然后摁下n键。

以下所有的prefix均代表CTRL+b

会话相关操作

操作 快捷键
查看/切换会话 前缀 s
离开会议 前缀 d
重命名当前Session 前缀 $

窗口相关操作

操作 快捷键
新建窗口 前缀 c
切换到上一个活动的窗口 前缀空格
关闭一个窗口 前缀 &
使用窗口号切换 前缀窗口号

面板相关操作

操作 快捷键
切换到下一个 前缀 o
查看所有上述的编号 前缀 q
垂直拆分出一个新的一个 前缀“
水平拆分产生一个新的一个 前缀 %
暂时把一个放置最大 前缀 z

tmux的一些个性化定制

默认的tmux风格比较朴素甚至有些丑陋。如果希望做一些美化和个性化配置的话,建议使用gpakosz的tmux配置。它的本质是一个tmux配置文件,实现了以下功能:

  • 基于电力线的美化
  • 显示笔记本电池电量
  • 和Mac互通的剪切板
  • 和vim更近的快捷键

安装方式也很简单如下(注意:如果想使用powerline美化需要先安装powerline,具体方法见之前的博文

$ cd
$ rm -rf .tmux
$ git clone https://github.com/gpakosz/.tmux.git
$ ln -s .tmux/.tmux.conf
$ cp .tmux/.tmux.conf.local .

安装完成以后可以获得以下效果了:

电力线

 
 
posted @ 2026-03-22 16:32  CharyGao  阅读(1)  评论(0)    收藏  举报