木匣子

Web/Game/Programming/Life etc.

助你同时维护多个项目的终端神器:Tmux

最近工作中需要来回在几个项目间切换,即使是使用支持多标签的终端感觉也有点不够用。于是开始寻找新的解决方案。最后遇到了 tmux 感觉有点相见恨晚。

Tmux 是一个虚拟终端管理工具,或者叫终端复用器(Terminal Multiplexer)。它支持同屏多面板(Panel)、多窗口(Window)、多会话(Session),还能够后台挂起、恢复。这些抽象概念都是为了帮助你快速地从中断状态回到工作状态。

终端复用这个概念我之前有接触过。最早的时候使用过的一款叫 GNU Screen 的工具。当你远程登陆到服务器上的时候,由于各种原因断开连接,再重联到服务器,之前在终端运行的各种脚本就不见了,正在运行的程序也会被终止。而 Screen 相当于在服务端运行一个守护进程(Daemon),当你挂起当前终端的时候,它并没有被真的关掉,而是原地待命,直到你再次接入,先前的终端就像没有被动过一样。

而 Tmux 不仅延续了这些基本理念,还发展出了一套非常高级的终端管理方案。此外开源社区还提供了大量优秀的插件给大家自定义。本文简单记录一下我的 Tmux 使用过程。

Tmux

如果你和我一样是 macOS 用户,直接通过 brew 安装即可:

$ brew install tmux
$ tmux -V
tmux 3.0a

在使用 tmux 之前,我推荐看一下 Tmux Cheatsheet 这个网站,上面有非常简明的 tmux 操作说明。如果忘了操作,可以随时打开瞄一眼。快捷键这种东西基本上前期靠查,后期就熟能生巧了,不需要死记硬背。

简单总结一下 tmux 的一些抽象概念:

会话 / Session

每次启动 tmux,它都会连接或者创建一个会话。我习惯以项目来划分会话,并以项目名来命名会话。工作的时候会运行多个会话来支持多个项目。

窗口 / Window

每个会话由一到多个窗口组成,当所有窗口被关闭,会话就结束。我习惯在多个窗口中执行不同的占屏进程,例如 webpack devstorybook dev ,这些进程一运行就会占用窗口,期间你只能看到日志输出,做不了其它事。于是我们可以在会话中新开一个窗口,做其它的业务,需要的时候再切回来看一下输出。这也是 tmux 的重要理念。

面板 / Panel

如果你的屏幕非常大,想直接在同一个窗口中进行不同的工作,tmux 还提供了面板功能,你可以在一个窗口中划分出小面板,然后辗转于这些小面板中。适用于需要同时参考不同输出或文件的业务。我主要的开发工作在其它 IDE 上,所以这个功能我用得比较少。

配置 / Config

如果想把 tmux 用得利索,免不了要对 tmux 进行一番定制,我们可以创建并编辑 ~/.tmux.config 文件,这里有一份官方的配置样本可供参考。这里也展示一下我的配置:

# remap prefix from 'C-b' to 'C-q'
unbind C-b
set-option -g prefix C-q
bind-key C-q send-prefix

# Start windows and panes at 1, not 0
set -g base-index 1
setw -g pane-base-index 1

# allow mouse to scroll the screen
setw -g mouse on 

# fix the macOS Majove clipboard issue
set-option -g default-command "reattach-to-user-namespace -l $SHELL"

# List of plugins
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'
set -g @plugin 'tmux-plugins/tmux-resurrect'
set -g @plugin 'tmux-plugins/tmux-yank'

# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)
run -b '~/.tmux/plugins/tpm/tpm'

大概介绍一下我的定制:

  • 将主键 Ctrl-b 修改成 Ctrl-q。因为这个键更接近数字键,方便切换窗口,此外 Ctrl-q 比较少用,不会与其它的操作冲突。有的人建议换成 Ctrl-a,不过后者是一个很常用的光标跳转键。
  • 将窗口索引的基数设置为 1 而不是 0,因为在 86 键盘上,数字键 0 离键 1 太远,不方便切换头两个常用窗口。
  • 使用鼠标滚轮滚动屏幕,而非进入编辑状态。方便浏览较长的日志。
  • 需要另外安装 reattach-to-user-namespace 来修复 macOS Majove 10.14 的复制粘贴问题,最新的 macOS Catalina 10.15 不需要此配置。详情见此文
  • 一些插件,详见下文。

Tpm

Tmux 插件管理器(Tmux Plugins Manager),可以方便地管理 tmux 插件。为扩展 tmux 打开了一扇大门。使用 git 安装,然后在 .tmux.conf 中配置,具体操作说明可以在 github 上的官方仓库中找到。

这里介绍一下我使用的几个插件:

  • tmux-plugins/tpm - tpm 自身,提供了插件的安装、更新、删除流程的快捷键。
  • tmux-plugins/tmux-sensible - 基础配置,一些非常常用的配置,被社区称为「共识」。
  • tmux-plugins/tmux-resurrect - tmux 虽然能够维持会话,但是一旦操作系统被重启,这些会话仍然会丢失。而 resurrect 的作用就是在让你在系统被关掉前有机会保存所有会话,并在之后任意时间恢复保存的会话。
  • tmux-plugins/tmux-yank - 一个更便捷的剪切板插件。

更多的插件可以在前文提到的 Tmux Cheatsheet 网站找到。

Tmuxinator

Tmuxinator 是 Tmux 的一个辅助工具。它提供了一种快速创建会话的能力,你可以把一个项目需要用到的窗口和面板写到配置文件中 .tmuxinator.yml,然后用 Tmuxinator 启动它。相比前文提到的 tmux-resurrect 插件,我更喜欢使用 tmuxinator,它除了恢复会话的能力,还能在创建创建的时候预先进行一些脚本,例如设置环境变量、代理,启动相应的进程等等。

但是由于它的名字太长了,大家会给它加个别名 mux 方便使用。

# append this line to your ~/.profile
alias mux=tmuxinator

以上就是我的 tmux 使用心得。