Tmux奇技淫巧

Tmux奇技淫巧

Tmux奇技淫巧

在日常的开发工作中,终端是我们最常用的工具之一。在终端中我们可以调用各种解释器,来执行命令,完成我们的工作。然而,对于只使用终端的默认功能的开发者来说,他们可能会错过一些强大的工具和技巧,这些工具和技巧可以大大提高工作效率。

其中一个非常有用的终端工具就是TmuxTmux是一个终端复用器,它允许我们在一个终端窗口中同时运行多个终端会话,并提供了许多有用的功能,如会话管理、窗口分割、窗格布局等。本文将介绍Tmux的基本概念和一些常用的功能,帮助读者更好地利用Tmux提升终端工作效率。

你当然可以使用oh-my-tmux,但是学习基础知识能够帮助你更好的使用这些工具。

1. Why Tmux?

1.1 终端复用

想象这样一个场景,我们通过ssh连接到了远程服务器之后,默认我们会连接到一个交互式解释器中(例如bashzsh)。在同一个交互式解释器中,每次只能运行一条命令,而后等到命令运行结束之后我们才能再运行下一条命令。但很多时候,我们希望能连接到多个解释器,并行执行多个命令。

例如,假设你是一名软件开发者,正在进行一个大型项目的开发工作。为了方便开发,我们需要同时进行多个任务,如运行应用程序、查看日志、执行命令等。

  • 首先,你创建了一个窗口,并将其命名为"代码编辑"。在这个窗口中,你打开了代码编辑器,并开始编写项目的代码。这个窗口用于代码编辑,而为了查看终端的输出,我们还需要创建另外一个窗口
  • 接下来,你创建了另一个窗口,并将其命名为"测试"。在这个窗口中,我们运行测试脚本和查看测试结果。
  • 同时,你还创建了一个名为"服务器"的窗口,用于连接到远程服务器并执行一些部署和管理任务。

在这个场景下,为了完成我们的开发工作,我们打开了多个不同的窗口,而每次切换窗口时都手都需要离开键盘,去点击鼠标。这样一来我们的效率就会被极大地降低。

想象现在有一个软件:

  • 我们可以通过它创建了一个和解释器的会话。在这个会话中,你可以同时进行多个任务,如运行应用程序、查看日志、执行命令等。
  • 其次利用它我们能创建一个窗口,并将其命名为"代码编辑"。在这个窗口中,你打开了代码编辑器,并开始编写项目的代码。而后利用它,我们能将窗口水平分割成两个窗格,一个用于编辑代码,另一个用于查看终端输出。
  • 接下来,你创建了另一个窗口,并将其命名为"测试"。在这个窗口中,你打开了一个终端,用于运行测试脚本和查看测试结果。你可以通过它提供的快捷键在不同的窗口之间快速切换,方便地在编写代码和运行测试之间进行切换。
  • 最后,你还创建了一个名为"服务器"的窗口,用于连接到远程服务器并执行一些部署和管理任务。你可以在这个窗口中使用它提供窗格布局功能,将窗口垂直分割成两个窗格,一个用于连接到服务器,另一个用于执行命令和查看日志。

通过使用这个软件,你可以在同一个终端窗口中同时进行代码编辑、测试和服务器管理等多个任务,而无需打开多个终端窗口。你可以通过它的快捷键快速切换窗口和窗格,轻松地在不同任务之间切换,提高工作效率。

将一个窗口分为多个窗格,分别运行不同的命令

1.2 持久性会话

另外一个场景是,假设你正在远程连接到一台服务器,并需要在该服务器上运行一个需要较长时间才能完成的任务,比如数据处理、模型训练或后台服务。

  • 那么我们连接到服务器并启动任务后,并希望在断开SSH连接后继续运行。这意味着即使你的SSH会话中断或你关闭了终端窗口,任务仍会在后台继续运行。这对于长时间运行的任务非常有用,因为你不必担心任务被中断或终止。
  • 但是SSH默认连接的终端在我们关闭SSH连接后就会终止运行,相应的我们还在运行的任务也会被终止。

因此,在这个场景下,我们希望可以和终端进行持久性会话,这样就关闭SSH链接或者关闭终端窗口后再次打开,你仍然可以恢复到之前的工作状态。

SSH链接断开后命令依旧在运行

2. 安装Tmux

2.1 包管理器安装

在大多数Linux发行版中,可以使用包管理器进行安装。例如,在Ubuntu上,可以使用以下命令进行安装:

sudo apt-get install tmux

2.2 手动编译安装

作为追求技术的程序员,我们当然也可以手动从源码编译安装,毕竟这样更酷。而且包管理器的软件源中的版本可能比较老,因此手动编译安装也是不错的选择。

首先下载并解压源代码

mkdir ~/opt/tmux && cd ~/opt/tmux
wget -c https://github.com/tmux/tmux/releases/download/3.3a/tmux-3.3a.tar.gz
tar xzvf tmux-3.3a.tar.gz
mkdir v3.3a && mv tmux* v3.3a

然后编译

cd v3.3a/tmux-3.3a
./configure --prefix=/home/jack/opt/tmux/v3.3a/
make -j $(nproc)
make install

编译完成后,就能看到已经有tmux

cd ..
tree -L 2 -I tmux-3.3a

image-20231101145125289

最后创建一个软连接,方便未来版本更新。

ln -s v3.3a/bin bin
ln -s v3.3a/share share
ll

完成tmux安装

PS:别忘了添加环境变量。

echo 'export PATH="/home/jack/opt/tmux/bin:${PATH}"' >> ~/.zshrc 

3. Tmux基础概念

开始之前,我们先了解下Tmux的基本概念:

  • Tmux采用C/S模型构建,输入Tmux命令就相当于链接到了Tmux服务器,此时默认将新建一个会话,然后会话中默认新建一个窗口,窗口中默认新建一个面板
  • 当前的会话会被保存在Tmux服务器中,即便我们退出了这个会话,下次还可以重新连接到这个回话中,其中运行的命令不会被中断

Tmux的会话、窗口、面板之间的联系如下:

  • 一个Tmux session(会话)可以包含多个window(窗口),窗口默认充满会话界面,因此这些窗口中可以运行相关性不大的任务。
  • 一个window又可以包含多个pane(面板),窗口下的面板,都处于同一界面下,这些面板适合运行相关性高的任务,以便同时观察到它们的运行情况。

Tmux中会话、窗口和面板的关系

4. Tmux的基础使用

4.1 会话操作

新建会话

新建一个tmux session非常简单,语法为tmux new -s session-name,也可以简写为tmux,为了方便管理,建议指定会话名称,如下。

tmux # 新建一个无名称的会话
tmux new -s demo # 新建一个名称为demo的会话

注意,Tmux默认是不允许session之间嵌套的,因此这个命令需要在session外使用

进入会话后,终端的下面就会显示绿色的状态栏,其中描述了诸多信息。

断开当前会话

会话中操作了一段时间,我希望断开会话同时下次还能接着用,怎么做?此时可以使用detach命令。

tmux detach # 断开当前会话,会话在后台运行

也许你觉得这个太麻烦了,是的,tmux的会话中,我们可以使用tmux快捷键了。使用快捷键组合Ctrl+b + d,三次按键就可以断开当前会话。

进入之前的会话

断开会话后,想要接着上次留下的现场继续工作,就要使用到tmux的attach命令了,语法为tmux attach-session -t session-name,可简写为tmux a -t session-nametmux a。通常我们使用如下两种方式之一即可:

tmux a # 默认进入第一个会话
tmux a -t demo # 进入到名称为demo的会话
关闭会话

会话的使命完成后,一定是要关闭的。我们可以使用tmux的kill命令,kill命令有kill-panekill-serverkill-sessionkill-window共四种,其中kill-session的语法为tmux kill-session -t session-name。如下:

tmux kill-session -t demo # 关闭demo会话
tmux kill-server # 关闭服务器,所有的会话都将关闭
查看所有的会话

管理会话的第一步就是要查看所有的会话,我们可以使用如下命令:

tmux list-session # 查看所有会话
tmux ls # 查看所有会话,提倡使用简写形式

如果刚好处于会话中怎么办?别担心,我们可以使用对应的tmux快捷键Ctrl+b + s,此时tmux将打开一个会话列表,按上下键(⬆︎⬇︎)或者鼠标滚轮,可选中目标会话,按左右键可收起或展开会话的窗口,选中目标会话或窗口后,按回车键即可完成切换。

Tmux查看所有会话

重命名会话

tmux rename-session命令用于重命名会话。

tmux rename-session -t 0 <new-name>

上面命令将0号会话重命名。

但事实上一般更常用的是重命名当前会话,所以直接使用快捷键Ctrl+b + $

4.2 窗口操作

新建窗口

tmux new-window命令用来创建新窗口。

tmux new-window
# 新建一个指定名称的窗口
tmux new-window -n <window-name>
切换窗口

tmux select-window命令用来切换窗口。

# 切换到指定编号的窗口
tmux select-window -t <window-number>

# 切换到指定名称的窗口
tmux select-window -t <window-name>
重命名窗口

tmux rename-window命令用于为当前窗口起名(或重命名)。

tmux rename-window <new-name>
窗口快捷键

下面是一些窗口操作的快捷键。

  • Ctrl+b c:创建一个新窗口,状态栏会显示多个窗口的信息。
  • Ctrl+b p:切换到上一个窗口(按照状态栏上的顺序)。
  • Ctrl+b n:切换到下一个窗口。
  • Ctrl+b <number>:切换到指定编号的窗口,其中的<number>是状态栏上的窗口编号。
  • Ctrl+b w:从列表中选择窗口。
  • Ctrl+b ,:窗口重命名。

更多的命令就不介绍了,因为相比于使用命令来说,更常用的是直接使用快捷键。

5. Tmux快捷键

关于快捷键,首先要认识到的是:tmux的所有快捷键,都包含同一个前缀,默认为Ctrl+b,输入完前缀过后,控制台激活,命令按键才能生效。前面tmux会话相关的操作中,我们共用到了两个快捷键Ctrl+b + dCtrl+b + s,但这仅仅是冰山一角,欲窥tmux庞大的快捷键体系,请看下表。

5.1 Tmux系统指令

前缀指令描述
Ctrl+b?显示快捷键帮助文档
Ctrl+bd断开当前会话
Ctrl+bD选择要断开的会话
Ctrl+bCtrl+z挂起当前会话
Ctrl+br强制重载当前会话
Ctrl+bs显示会话列表用于选择并切换
Ctrl+b:进入命令行模式,此时可直接输入ls等命令
Ctrl+b[进入复制模式,按q退出
Ctrl+b]粘贴复制模式中复制的文本
Ctrl+b~列出提示信息缓存

5.2 窗口(window)指令。

前缀指令描述
Ctrl+bc新建窗口
Ctrl+b&关闭当前窗口(关闭前需输入y or n确认)
Ctrl+b0~9切换到指定窗口
Ctrl+bp切换到上一窗口
Ctrl+bn切换到下一窗口
Ctrl+bw打开窗口列表,用于且切换窗口
Ctrl+b,重命名当前窗口
Ctrl+b.修改当前窗口编号(适用于窗口重新排序)
Ctrl+bf快速定位到窗口(输入关键字匹配窗口名称)

5.3 面板(pane)指令。

前缀指令描述
Ctrl+b"当前面板上下一分为二,下侧新建面板
Ctrl+b%当前面板左右一分为二,右侧新建面板
Ctrl+bx关闭当前面板(关闭前需输入y or n确认)
Ctrl+bz最大化当前面板,再重复一次按键后恢复正常(v1.8版本新增)
Ctrl+b!将当前面板移动到新的窗口打开(原窗口中存在两个及以上面板有效)
Ctrl+b;切换到最后一次使用的面板
Ctrl+bq显示面板编号,在编号消失前输入对应的数字可切换到相应的面板
Ctrl+b{向前置换当前面板
Ctrl+b}向后置换当前面板
Ctrl+bCtrl+o顺时针旋转当前窗口中的所有面板
Ctrl+b方向键移动光标切换面板
Ctrl+bo选择下一面板
Ctrl+b空格键在自带的面板布局中循环切换
Ctrl+bAlt+方向键以5个单元格为单位调整当前面板边缘
Ctrl+bCtrl+方向键以1个单元格为单位调整当前面板边缘(Mac下被系统快捷键覆盖)
Ctrl+bt显示时钟

tmux的丝滑分屏功能正是得益于以上系统、窗口、面板的快捷指令,只要你愿意,你就可以解除任意的快捷指令,然后绑上你喜欢的指令,当然这就涉及到tmux的配置了。

6. Tmux的配置文件

类似于.bashrc.zshrc,tmux提供了类似的配置文件。通过编写配置文件就可以实现更加强大的功能。

tmux的用户级配置文件为~/.tmux.conf(没有的话就创建一个),修改快捷指令,只需要增加如下三行即可。如果你的主目录下还没有 .tmux.conf 文件,你可以使用文本编辑器创建一个新的文件并将其保存为 .tmux.conf

配置文件使用简单的语法来定义设置和命令。每个设置或命令占据一行,可以使用 # 符号进行注释。

6.0 Tmux配置文件的指令

在 Tmux 配置文件中,可以使用以下几类命令:

  1. set 命令:用于设置各种选项和参数。可以使用 set -g 命令设置全局选项,使用 set -u 命令取消选项设置,使用 set -g option value 命令设置具体的选项和对应的值。例如,set -g prefix C-a 将前缀键设置为 Ctrl+a

  2. bind-key 命令:用于创建键绑定,将特定的键映射到指定的命令。可以使用 bind-key -n 命令创建无前缀键绑定,使用 bind-key 命令创建带前缀键绑定。例如,bind-key -n C-a new-windowCtrl+a 绑定到新建窗口的命令。

  3. unbind-key 命令:用于解除键绑定,取消特定键的映射。可以使用 unbind-key -n 命令解除无前缀键绑定,使用 unbind-key 命令解除带前缀键绑定。例如,unbind-key -n C-a 将取消 Ctrl+a 的绑定。

  4. source-file 命令:用于重新加载配置文件,使新的设置生效。可以使用 source-file ~/.tmux.conf 命令重新加载主配置文件。这在你编辑完配置文件后需要使更改生效时非常有用。

  5. alias 命令:用于创建命令别名。可以使用 alias -g 命令创建全局别名,使用 alias 命令创建局部别名。例如,alias -g L "list-sessions"L 定义为 list-sessions 命令的别名。

这些命令可以在 Tmux 配置文件中使用,用于自定义和配置 Tmux 的行为、键绑定、外观和其他选项。通过合理使用这些命令,你可以根据自己的需求创建一个适合自己的 Tmux 环境。

下面就介绍一些常用的配置。

6.1 修改指令前缀

相信只要你用过几次tmux,就会发现Ctrl+b指令前缀,着实不太方便。这两个键相距太远,按键成本太高了。因此我们首先需要将它更换为距离更近的Ctrl+a组合键,或者不常用的 ` 键。

set -g prefix C-a # 将快捷键前缀设置为Ctrl+a
unbind C-b # C-b即Ctrl+b键,unbind意味着解除绑定
bind C-a send-prefix # 绑定Ctrl+a为新的指令前缀

# 从tmux v1.6版起,支持设置第二个指令前缀
set-option -g prefix2 ` # 设置一个不常用的`键作为指令前缀,按键更快些

修改的~/.tmux.conf配置文件有如下两种方式可以令其生效:

  • restart tmux。
  • 在tmux窗口中,先按下Ctrl+b指令前缀,然后按下系统指令:,进入到命令模式后输入source-file ~/.tmux.conf,回车后生效。

6.2 加载配置文件快捷键

既然快捷键如此方便,更为优雅的做法是新增一个加载配置文件的快捷键 ,这样就可以随时随地load新的配置了,如下所示。

# 绑定快捷键为r
bind r source-file ~/.tmux.conf \; display-message "Config reloaded.."

请特别注意,在已经创建的窗口中,即使加载了新的配置,旧的配置依然有效(只要你新加的功能没有覆盖旧的配置,因此如果你第一次绑定快捷指令为x键,然后又改为绑定y键,那么xy都将有效),新建会话不受此影响,将直接采用新的配置。

既然我们已经迈出配置化的第一步,那么接下来我们可以做得更多。

6.3 新增面板

tmux中,使用最多的功能之一就是新增一个面板。水平方向新增面板的指令是 prefix + " ,垂直方向是 prefix + %"%需要两个键同时按下才能完成,加上指令前缀至少需要3~4次按键才能组成一个完整的指令,同时这个两个键也不够醒目和方便,因此我们可以绑定两个更常用的指令 -|,如下所示:

unbind '"'
bind - splitw -v -c '#{pane_current_path}' # 垂直方向新增面板,默认进入当前目录
unbind %
bind | splitw -h -c '#{pane_current_path}' # 水平方向新增面板,默认进入当前目录

6.4 开启鼠标支持

默认情况下,tmux的多窗口之间的切换以及面板大小调整,需要输入指令才能完成,这一过程,涉及到的指令较多,而且操作麻烦,特别是面板大小调整,指令难以一步到位,这个时候开启鼠标支持就完美了。

对于tmux v2.1(2015.10.28)之前的版本,需加入如下配置:

setw -g mode-mouse on # 支持鼠标选取文本等
setw -g mouse-resize-pane on # 支持鼠标拖动调整面板的大小(通过拖动面板间的分割线)
setw -g mouse-select-pane on # 支持鼠标选中并切换面板
setw -g mouse-select-window on # 支持鼠标选中并切换窗口(通过点击状态栏窗口名称)

有的地方可能会出现set-window-option的写法,setw就是它的别名。

对于tmux v2.1及以上的版本,仅需加入如下配置:

set-option -g mouse on # 等同于以上4个指令的效果

需要注意的是,开启鼠标支持后,iTem2默认的鼠标选中即复制功能需要同时按下 Alt 键,才会生效。

6.5 快速面板切换

鼠标支持确实能带来很大的便捷性,特别是对于习惯了鼠标操作的tmux新手,但对于键盘爱好者而言,这不是什么好消息,对他们而言,双手不离键盘是基本素质。

虽然指令前缀加方向键可以切换面板,但方向键太远,不够快,不够Geek。没关系,我们可以将面板切换升级为熟悉的hjkl键位。

# 绑定hjkl键为面板切换的上下左右键
bind -r k select-pane -U # 绑定k为↑
bind -r j select-pane -D # 绑定j为↓
bind -r h select-pane -L # 绑定h为←
bind -r l select-pane -R # 绑定l为→

-r表示可重复按键,大概500ms之内,重复的hjkl按键都将有效,完美支持了快速切换的Geek需求。

除了上下左右外, 还有几个快捷指令可以设置。

bind -r e lastp # 选择最后一个面板
bind -r ^e last # 选择最后一个窗口

bind -r ^u swapp -U # 与前一个面板交换位置
bind -r ^d swapp -D # 与后一个面板交换位置

6.6 面板大小调整

习惯了全键盘操作后,命令的便捷性不言而喻。既然面板切换的指令都可以升级,面板大小调整的指令自然也不能落后。如下配置就可以升级你的操作:

# 绑定Ctrl+hjkl键为面板上下左右调整边缘的快捷指令
bind -r ^k resizep -U 10 # 绑定Ctrl+k为往↑调整面板边缘10个单元格
bind -r ^j resizep -D 10 # 绑定Ctrl+j为往↓调整面板边缘10个单元格
bind -r ^h resizep -L 10 # 绑定Ctrl+h为往←调整面板边缘10个单元格
bind -r ^l resizep -R 10 # 绑定Ctrl+l为往→调整面板边缘10个单元格

以上,resizepresize-pane的别名。

6.7 面板最大化

当窗口中面板的数量逐渐增多时,每个面板的空间就会逐渐减少。为了保证有足够的空间显示内容,tmux从v1.8版本起,提供了面板的最大化功能,输入tmux-prefix+z,就可以最大化当前面板至窗口大小,只要再重复输入一次,便恢复正常。

6.8 窗口变为面板

面板可以轻松地最大化为一个新的窗口。那么反过来,窗口是不是可以最小化为一个面板呢?

试想这样一个场景:当你打开多个窗口后,然后想将其中几个窗口合并到当前窗口中,以便对比观察输出。

实际上,你的要求就是将其它窗口变成面板,然后合并到当前窗口中。对于这种操作,我们可以在当前窗口,按下prefix + :,打开命令行,然后输入如下命令:

join-pane -s window01 # 合并名称为window01的窗口的默认(第一个)面板到当前窗口中
join-pane -s window01.1 # .1显式指定了第一个面板,.2就是第二个面板(我本地将面板编号起始值设置为1,默认是0)

每次执行join-pane命令都会合并一个面板,并且指定的窗口会减少一个面板,直到面板数量为0,窗口关闭。

除了在当前会话中操作外,join-pane命令甚至可以从其它指定会话中合并面板,格式为join-pane -s [session_name]:[window].[pane],如join-pane -s 2:1.1 即合并第二个会话的第一个窗口的第一个面板到当前窗口,当目标会话的窗口和面板数量为0时,会话便会关闭。

注:上一节中的swap-pane命令与join-pane语法基本一致。

6.9 其他配置

bind m command-prompt "splitw -h 'exec man %%'"   # 绑定m键为在新的panel打开man
# 绑定P键为开启日志功能,如下,面板的输出日志将存储到桌面
bind P pipe-pane -o "cat >>~/Desktop/#W.log" \; display "Toggled logging to ~/Desktop/#W.log"

6.10 恢复用户空间

tmux会话中,Mac的部分命令如 osascriptopenpbcopypbpaste等可能会失效(失效命令未列全)。

部分bug列表如下:

对此,我们可以通过安装reattach-to-user-namespace包装程序来解决这个问题。

brew install reattach-to-user-namespace

~/.tmux.conf中添加配置:

set -g default-command "reattach-to-user-namespace -l $SHELL"

这样你的交互式shell最终能够重新连接到用户级的命名空间。由于连接状态能够被子进程继承,故以上配置保证了所有从 shell 启动的命令能够被正确地连接。

有些时候,我们可能会在不同的操作系统中共享配置文件,如果你的tmux版本大于1.9,我们还可以使用if-shell来判断是否Mac系统,然后再指定default-command

if-shell 'test "$(uname -s)" = Darwin' 'set-option -g default-command "exec reattach-to-user-namespace -l $SHELL"'

对于tmux v1.8及更早的版本,可以使用如下包装后的配置:

set-option -g default-command 'command -v reattach-to-user-namespace >/dev/null && exec reattach-to-user-namespace -l "$SHELL" || exec "$SHELL"'

以上,$SHELL对应于你的默认Shell,通常是/usr/bin/bash/usr/local/bin/zsh

7. 复制模式

tmux中操作文本,自然离不开复制模式,通常使用复制模式的步骤如下:

  1. 输入 ``+[` 进入复制模式
  2. 按下 空格键 开始复制,移动光标选择复制区域
  3. 按下 回车键 复制选中文本并退出复制模式
  4. 按下 ``+]` 粘贴文本

查看复制模式默认的快捷键风格:

tmux show-window-options -g mode-keys # mode-keys emacs

默认情况下,快捷键为emacs风格。

为了让复制模式更加方便,我们可以将快捷键设置为熟悉的vi风格,如下:

setw -g mode-keys vi # 开启vi风格后,支持vi的C-d、C-u、hjkl等快捷键

7.1 自定义复制和选择快捷键

除了快捷键外,复制模式的启用、选择、复制、粘贴等按键也可以向vi风格靠拢。

bind Escape copy-mode # 绑定esc键为进入复制模式
bind -t vi-copy v begin-selection # 绑定v键为开始选择文本
bind -t vi-copy y copy-selection # 绑定y键为复制选中文本
bind p pasteb # 绑定p键为粘贴文本(p键默认用于进入上一个窗口,不建议覆盖)

以上,绑定 vy两键的设置只在tmux v2.4版本以下才有效,对于v2.4及以上的版本,绑定快捷键需要使用 -T 选项,发送指令需要使用 -X 选项,请参考如下设置:

bind -T copy-mode-vi v send-keys -X begin-selection
bind -T copy-mode-vi y send-keys -X copy-selection-and-cancel

7.2 Buffer缓存

tmux复制操作的内容默认会存进buffer里,buffer是一个粘贴缓存区,新的缓存总是位于栈顶,它的操作命令如下:

tmux list-buffers # 展示所有的 buffers
tmux show-buffer [-b buffer-name] # 显示指定的 buffer 内容
tmux choose-buffer # 进入 buffer 选择页面(支持jk上下移动选择,回车选中并粘贴 buffer 内容到面板上)
tmux set-buffer # 设置buffer内容
tmux load-buffer [-b buffer-name] file-path # 从文件中加载文本到buffer缓存
tmux save-buffer [-a] [-b buffer-name] path # 保存tmux的buffer缓存到本地
tmux paste-buffer # 粘贴buffer内容到会话中
tmux delete-buffer [-b buffer-name] # 删除指定名称的buffer

以上buffer操作在不指定buffer-name时,默认处理是栈顶的buffer缓存。

在tmux会话的命令行输入时,可以省略上述tmux前缀,其中list-buffers的操作如下所示:

list-buffers

choose-buffer的操作如下所示:

choose-buffer

默认情况下,buffers内容是独立于系统粘贴板的,它存在于tmux进程中,且可以在会话间共享。

7.3 使用系统粘贴板

存在于tmux进程中的buffer缓存,虽然可以在会话间共享,但不能直接与系统粘贴板共享,不免有些遗憾。幸运的是,现在我们有成熟的方案来实现这个功能。

A. 在Linux上使用粘贴板

通常,Linux中可以使用xclip工具来接入系统粘贴板。

首先,需要安装xclip

sudo apt-get install xclip

然后,.tmux.conf的配置如下。

# buffer缓存复制到Linux系统粘贴板
bind C-c run " tmux save-buffer - | xclip -i -sel clipboard"
# Linux系统粘贴板内容复制到会话
bind C-v run " tmux set-buffer \"$(xclip -o -sel clipboard)\"; tmux paste-buffer"

按下prefix + Ctrl + c 键,buffer缓存的内容将通过xlip程序复制到粘贴板,按下prefix + Ctrl + v键,tmux将通过xclip访问粘贴板,然后由set-buffer命令设置给buffer缓存,最后由paste-buffer粘贴到tmux会话中。

B. 在Mac上使用粘贴板

我们都知道,Mac自带 pbcopypbpaste命令,分别用于复制和粘贴,但在tmux命令中它们却不能正常运行。这里我将详细介绍下原因:

Mac的粘贴板服务是在引导命名空间注册的。命名空间存在层次之分,更高级别的命名空间拥有访问低级别命名空间(如root引导命名空间)的权限,反之却不行。流程创建的属于Mac登录会话的一部分,它会被自动包含在用户级的引导命名空间中,因此只有用户级的命名空间才能访问粘贴板服务。tmux使用守护进程(3)库函数创建其服务器进程,在Mac OS X 10.5中,苹果改变了守护进程(3)的策略,将生成的过程从最初的引导命名空间移到了根引导命名空间。而根引导命名空间访问权限较低,这意味着tmux服务器,和它的子进程,一同失去了原引导命名空间的访问权限(即无权限访问粘贴板服务)。

如此,我们可以使用一个小小的包装程序来重新连接到合适的命名空间,然后执行访问用户级命名空间的粘贴板服务,这个包装程序就是reattach-to-user-namespace

那么,Mac下.tmux.conf的配置如下:

# buffer缓存复制到Mac系统粘贴板
bind C-c run "tmux save-buffer - | reattach-to-user-namespace pbcopy"
# Mac系统粘贴板内容复制到会话
bind C-v run "reattach-to-user-namespace pbpaste | tmux load-buffer - \; paste-buffer -d"

reattach-to-user-namespace 作为包装程序来访问Mac粘贴板,按下prefix + Ctrl + c 键,buffer缓存的内容将复制到粘贴板,按下prefix + Ctrl + v键,粘贴板的内容将通过 load-buffer 加载,然后由 paste-buffer 粘贴到tmux会话中。

为了在复制模式中使用Mac系统的粘贴板,可做如下配置:

# 绑定y键为复制选中文本到Mac系统粘贴板
bind-key -T copy-mode-vi 'y' send-keys -X copy-pipe-and-cancel 'reattach-to-user-namespace pbcopy'
# 鼠标拖动选中文本,并复制到Mac系统粘贴板
bind-key -T copy-mode-vi MouseDragEnd1Pane send -X copy-pipe-and-cancel "pbcopy"

完成以上配置后记得重启tmux服务器。至此,复制模式中,按y键将保存选中的文本到Mac系统粘贴板,随后按Command + v键便可粘贴。