一. tmux 简介
指令全
https://gist.github.com/ryerh/14b7c24dfd623ef8edc7
tmux是一款优秀的终端复用软件,它比Screen更加强大,至于如何强大,网上有大量的文章讨论了这点,本文不再重复。tmux之所以受人们喜爱,主要得益于以下三处功能:
- 丝滑分屏(split),虽然iTem2也提供了横向和竖向分屏功能,但这种分屏功能非常拙劣,完全等同于屏幕新开一个窗口,新开的pane不会自动进入到当前目录,也没有记住当前登录状态。这意味着如果我ssh进入到远程服务器时,iTem2新开的pane中,我依然要重新走一遍ssh登录的老路(omg)。tmux就不会这样,tmux窗口中,新开的pane,默认进入到之前的路径,如果是ssh连接,登录状态也依旧保持着,如此一来,我就可以随意的增删pane,这种灵活性,好处不言而喻。
- 保护现场(attach),即使命令行的工作只进行到一半,关闭终端后还可以重新进入到操作现场,继续工作。对于ssh远程连接而言,即使网络不稳定也没有关系,掉线后重新连接,可以直奔现场,之前运行中的任务,依旧在跑,就好像从来没有离开过一样;特别是在远程服务器上运行耗时的任务,tmux可以帮你一直保持住会话。如此一来,你就可以随时随地放心地进行移动办公,只要你附近的计算机装有tmux(没有你也可以花几分钟装一个),你就能继续刚才的工作。
- 会话共享(适用于结对编程或远程教学),将 tmux 会话的地址分享给他人,这样他们就可以通过 SSH 接入该会话。如果你要给同事演示远程服务器的操作,他不必直勾勾地盯着你的屏幕,借助tmux,他完全可以进入到你的会话,然后静静地看着他桌面上你风骚的键盘走位,只要他愿意,甚至还可以录个屏。
开始之前,我们先了解下基本概念:
tmux采用C/S模型构建,输入tmux命令就相当于开启了一个服务器,此时默认将新建一个会话,然后会话中默认新建一个窗口,窗口中默认新建一个面板。会话、窗口、面板之间的联系如下:
一个tmux session
(会话)可以包含多个window
(窗口),窗口默认充满会话界面,因此这些窗口中可以运行相关性不大的任务。
一个window
又可以包含多个pane
(面板),窗口下的面板,都处于同一界面下,这些面板适合运行相关性高的任务,以便同时观察到它们的运行情况。
server | 服务器。输入tmux命令时就开启了一个服务器。 |
---|---|
session | 会话。一个服务器可以包含多个会话。 |
window | 窗口。一个会话可以包含多个窗口。 |
pane | 面板。一个窗口可以包含多个面板。 |
二. tmux 安装和配置
1 新建会话
新建一个tmux session非常简单,语法为tmux new -s session-name
,也可以简写为tmux
,为了方便管理,建议指定会话名称,如下。
2 断开当前会话
会话中操作了一段时间,我希望断开会话同时下次还能接着用,怎么做?此时可以使用detach命令
也许你觉得这个太麻烦了,是的,tmux的会话中,我们已经可以使用tmux快捷键了。使用快捷键组合Ctrl+b
+ d
,三次按键就可以断开当前会话。
3 进入之前的会话
断开会话后,想要接着上次留下的现场继续工作,就要使用到tmux的attach命令了,语法为tmux attach-session -t session-name
,可简写为tmux a -t session-name
或 tmux a
。通常我们使用如下两种方式之一即可:
4 关闭会话
会话的使命完成后,一定是要关闭的。我们可以使用tmux的kill命令,kill命令有kill-pane
、kill-server
、kill-session
和 kill-window
共四种,其中kill-session
的语法为tmux kill-session -t session-name
。如下:
在会话内退出并删除session
5 查看会话
管理会话的第一步就是要查看所有的会话,我们可以使用如下命令:
如果刚好处于会话中怎么办?别担心,我们可以使用对应的tmux快捷键Ctrl+b
+ s
,此时tmux将打开一个会话列表,按上下键(⬆︎⬇︎)或者鼠标滚轮,可选中目标会话,按左右键(⬅︎➜)可收起或展开会话的窗口,选中目标会话或窗口后,按回车键即可完成切换。
6 tmux快捷命令
关于快捷指令,首先要认识到的是:tmux的所有指令,都包含同一个前缀,默认为Ctrl+b
,输入完前缀过后,控制台激活,命令按键才能生效。前面tmux会话相关的操作中,我们共用到了两个快捷键Ctrl+b
+ d
、Ctrl+b
+ s
,但这仅仅是冰山一角,欲窥tmux庞大的快捷键体系,请看下表。
Ctrl+b
+ s
进入信息列表,然后选中某个session或者window或者pane,然后按 x
,都可以删除
表一:系统指令。
前缀 | 指令 | 描述 |
---|---|---|
Ctrl+b | ? | 显示快捷键帮助文档 |
Ctrl+b | d | 断开当前会话 |
Ctrl+b | D | 选择要断开的会话 |
Ctrl+b | Ctrl+z | 挂起当前会话 |
Ctrl+b | r | 强制重载当前会话 |
Ctrl+b | s | 显示会话列表用于选择并切换 |
Ctrl+b | : | 进入命令行模式,此时可直接输入ls 等命令 |
Ctrl+b | [ | 进入复制模式,按q 退出 |
Ctrl+b | ] | 粘贴复制模式中复制的文本 |
Ctrl+b | ~ | 列出提示信息缓存 |
表二:窗口(window)指令。
前缀 | 指令 | 描述 |
---|---|---|
Ctrl+b | c | 新建窗口 |
Ctrl+b | & | 关闭当前窗口(关闭前需输入y or n 确认) |
Ctrl+b | 0~9 | 切换到指定窗口 |
Ctrl+b | p | 切换到上一窗口 |
Ctrl+b | n | 切换到下一窗口 |
Ctrl+b | w | 打开窗口列表,用于且切换窗口 |
Ctrl+b | , | 重命名当前窗口 |
Ctrl+b | . | 修改当前窗口编号(适用于窗口重新排序) |
Ctrl+b | f | 快速定位到窗口(输入关键字匹配窗口名称) |
Ctrl+b | z | 最大化窗口 |
表三:面板(pane)指令。
前缀 | 指令 | 描述 |
---|---|---|
Ctrl+b | " | 当前面板上下一分为二,下侧新建面板 |
Ctrl+b | % | 当前面板左右一分为二,右侧新建面板 |
Ctrl+b | x | 关闭当前面板(关闭前需输入y or n 确认) |
Ctrl+b | z | 最大化当前面板,再重复一次按键后恢复正常(v1.8版本新增) |
Ctrl+b | ! | 将当前面板移动到新的窗口打开(原窗口中存在两个及以上面板有效) |
Ctrl+b | ; | 切换到最后一次使用的面板 |
Ctrl+b | q | 显示面板编号,在编号消失前输入对应的数字可切换到相应的面板 |
Ctrl+b | { | 向前置换当前面板 |
Ctrl+b | } | 向后置换当前面板 |
Ctrl+b | Ctrl+o | 顺时针旋转当前窗口中的所有面板 |
Ctrl+b | 方向键 | 移动光标切换面板 |
Ctrl+b | o | 选择下一面板 |
Ctrl+b | 空格键 | 在自带的面板布局中循环切换 |
Ctrl+b | Alt+方向键 | 以5个单元格为单位调整当前面板边缘 |
Ctrl+b | Ctrl+方向键 | 以1个单元格为单位调整当前面板边缘(Mac下被系统快捷键覆盖) |
Ctrl+b | t | 显示时钟 |
Ctrl+b | x | 关闭当前面板 |
Ctrl+b | E | 等分面板 |
tmux的丝滑分屏功能正是得益于以上系统、窗口、面板的快捷指令,只要你愿意,你就可以解除任意的快捷指令,然后绑上你喜欢的指令,当然这就涉及到它的可配置性了
7 tmux滚屏
使用快捷键进入 copy-mode
模式,就可以利用方向键上下移动光标查看了,但是如果历史信息太多,一行一行未免太不爽了,该如何操作呢?
1.先打开配置文件:
2.将下面设置输入:
3.重新载入配置文件:
4.使用快捷键进入 copy-mode
模式,然后就可以像 vi
中一样操作了。
比如:Ctrl-u
向上滚半屏, Ctrl-d
向下滚半屏。
根据某关键字搜索:
使用快捷键进入 copy-mode
模式,然后按 /
,就可以输入关键字了,回车查找。
四. 恢复用户空间
1 复制模式
tmux中操作文本,自然离不开复制模式,通常使用复制模式的步骤如下:
- 输入 ``+[` 进入复制模式
- 按下
空格键
开始复制,移动光标选择复制区域 - 按下
回车键
复制选中文本并退出复制模式 - 按下 ``+]` 粘贴文本
查看复制模式默认的快捷键风格:
默认情况下,快捷键为emacs
风格。
为了让复制模式更加方便,我们可以将快捷键设置为熟悉的vi
风格,如下:
除了快捷键外,复制模式的启用、选择、复制、粘贴等按键也可以向vi
风格靠拢。
以上,绑定 v
、y
两键的设置只在tmux v2.4版本以下才有效,对于v2.4及以上的版本,绑定快捷键需要使用 -T
选项,发送指令需要使用 -X
选项,请参考如下设置:
2 buffer缓存
tmux复制操作的内容默认会存进buffer
里,buffer
是一个粘贴缓存区,新的缓存总是位于栈顶,它的操作命令如下:
|
|
以上buffer操作在不指定buffer-name时,默认处理是栈顶的buffer缓存。
在tmux会话的命令行输入时,可以省略上述tmux前缀,其中list-buffers的操作如下所示:
·
choose-buffer的操作如下所示:
默认情况下,buffers内容是独立于系统粘贴板的,它存在于tmux进程中,且可以在会话间共享。
3 使用系统粘贴板
存在于tmux进程中的buffer缓存,虽然可以在会话间共享,但不能直接与系统粘贴板共享,不免有些遗憾。幸运的是,现在我们有成熟的方案来实现这个功能。
在Linux上使用粘贴板
通常,Linux中可以使用xclip
工具来接入系统粘贴板。
首先,需要安装xclip
。
然后,.tmux.conf
的配置如下。
按下prefix
+ Ctrl
+ c
键,buffer缓存的内容将通过xlip
程序复制到粘贴板,按下prefix
+ Ctrl
+ v
键,tmux将通过xclip
访问粘贴板,然后由set-buffer命令设置给buffer缓存,最后由paste-buffer粘贴到tmux会话中。
在Mac上使用粘贴板
我们都知道,Mac自带 pbcopy
和 pbpaste
命令,分别用于复制和粘贴,但在tmux命令中它们却不能正常运行。这里我将详细介绍下原因:
Mac的粘贴板服务是在引导命名空间注册的。命名空间存在层次之分,更高级别的命名空间拥有访问低级别命名空间(如root引导命名空间)的权限,反之却不行。流程创建的属于Mac登录会话的一部分,它会被自动包含在用户级的引导命名空间中,因此只有用户级的命名空间才能访问粘贴板服务。tmux使用守护进程(3)库函数创建其服务器进程,在Mac OS X 10.5中,苹果改变了守护进程(3)的策略,将生成的过程从最初的引导命名空间移到了根引导命名空间。而根引导命名空间访问权限较低,这意味着tmux服务器,和它的子进程,一同失去了原引导命名空间的访问权限(即无权限访问粘贴板服务)。
如此,我们可以使用一个小小的包装程序来重新连接到合适的命名空间,然后执行访问用户级命名空间的粘贴板服务,这个包装程序就是reattach-to-user-namespace
。
那么,Mac下.tmux.conf
的配置如下:
reattach-to-user-namespace
作为包装程序来访问Mac粘贴板,按下prefix
+ Ctrl
+ c
键,buffer缓存的内容将复制到粘贴板,按下prefix
+ Ctrl
+ v
键,粘贴板的内容将通过 load-buffer 加载,然后由 paste-buffer 粘贴到tmux会话中。
为了在复制模式中使用Mac系统的粘贴板,可做如下配置:
完成以上配置后记得重启tmux服务器。至此,复制模式中,按y
键将保存选中的文本到Mac系统粘贴板,随后按Command
+ v
键便可粘贴。
六.保存Tmux会话
1 结对编程
tmux多会话连接实时同步的功能,使得结对编程成为了可能,这也是开发者最喜欢的功能之一。现在就差一步了,就是借助tmate把tmux会话分享出去。
tmate是tmux的管理工具,它可以轻松的创建tmux会话,并且自动生成ssh链接。
安装tmate
使用tmate新建一个tmux会话
此时屏幕下方会显示ssh url,如下所示:
查看tmate生成的ssh链接
生成的ssh url如下所示,其中一个为只读,另一个可编辑。
2 共享账号&组会话
使用tmate远程共享tmux会话,受制于多方的网络质量,必然会存在些许延迟。如果共享会话的多方拥有同一个远程服务器的账号,那么我们可以使用组会话
解决这个问题。
先在远程服务器上新建一个公共会话,命名为groupSession
。
其他用户不去直接连接这个会话,而是通过创建一个新的会话来加入上面的公共会话groupSession
。
此时两个用户都可以在同一个会话里操作,就会好像第二个用户连接到了groupSession
的会话一样。此时两个用户都可以创建新建的窗口,新窗口的内容依然会实时同步,但是其中一个用户切换到其它窗口,对另外一个用户没有任何影响,因此在这个共享的组会话中,用户各自的操作可以通过新建窗口来执行。即使第二个用户关闭otherSession
会话,共享会话groupSession
依然存在。
组会话在共享的同时,又保留了相对的独立,非常适合结对编程场景,它是结对编程最简单的方式,如果账号不能共享,我们就要使用下面的方案了。
3 独立账号&Socket共享会话
开始之前我们需要确保用户对远程服务器上同一个目录拥有相同的读写权限,假设这个目录为/var/tmux/
。
使用new-session(简写new)创建会话时,使用的是默认的socket位置,默认socket无法操作,所以我们需要创建一个指定socket文件的会话。
另一个用户进入时,需要指定socket文件加入会话。
这样,两个不同的用户就可以共享同一个会话了。
通常情况下,不同的用户使用不同的配置文件来创建会话,但是,使用指定socket文件创建的tmux会话,会话加载的是第一个创建会话的用户的~/.tmux.conf
配置文件,随后加入会话的其他用户,依然使用同一份配置文件。
八.Tmux优化
tmux作为终端复用软件,支持纯命令行操作也是其一大亮点。你既可以启用可视化界面创建会话,也可以运行脚本生成会话,对于tmux依赖者而言,编写几个tmux脚本批量维护会话列表,快速重启、切换、甚至分享部分会话都是非常方便的。可能会有人说为什么不用Tmux Resurrect呢?是的,Tmux Resurrect很好,一键恢复也很诱人,但是对于一个维护大量tmux会话的用户而言,一键恢复可能不见得好,分批次恢复可能是他(她)更想要的,脚本化的tmux就很好地满足了这点。
脚本中创建tmux会话时,由于不需要开启可视化界面,需要输入-d
参数指定会话后台运行,如下。
新建的会话,建议重命令会话的窗口名称,以便后续维护。
现在,可以在刚才的窗口中输入指令了。
一个面板占用一个窗口可能太浪费了,我们来分个屏吧。
现在一个窗口拥有上下两个面板,是时候创建一个新的窗口来运行更多的程序了。
另外新建窗口运行程序,有更方便的方式,比如使用 processes
选项。
新的窗口,我们尝试下水平分屏。
类似的脚本,我们可以编写一打,这样快速重启、切换、甚至分享会话都将更加便捷。