tmux使用教程

为什么要用 Tmux

tmux 在很多方面都很有用。就我而言,由于 tmux 允许随时随地断开或重新接入会话(Session),所以最大的作用就是在远程服务器上持久地保存工作状态。

例如,你可以在服务器上新建一个会话并命名为“nodeapi”,然后用它来挖掘 node REST API 的漏洞(这是我现在的项目)。或者假设你正在咖啡店里工作,需要编译一些代码,而编译要花费 2 个小时才能完成(如果是和我一起工作的话),这时你又不得不离开咖啡店。如果使用了 tmux,你就可以轻松地断开当前的会话,并于稍后方便时重新接入该会话,继续工作。

这真是太方便了。

“如何使用 tmux 才能打开多个会话,如何在会话中打开多个标签(Tab),如何在标签中打开多个窗口(Window),又如何在窗口中打开多个窗格(Pane)”,也许有些人对这些操作更感兴趣。而我很少这样做的,因为我不喜欢打开太多的——实际上是尽可能少地打开——这些东西。因此,这篇入门教程主要讲解的也是作为简单的可持久化远程会话模型的 tmux。

远程操作计算机的生活方式

机动性是 tmux 带给用户的最大价值。有很多开发者都是在服务器上进行所有工作的,他们只需从某处连接上服务器就可以开始工作了。有了 tmux(或者其他类似的工具),你就可以先坐在旧金山的某个咖啡店里开始在服务器上进行构建的工作,然后断开会话去赶飞机,待飞机降落到纽约市后再继续进行刚才的工作。

tmux 带来的另一个好处是在移动办公中,作为客户端的计算机变得不再那么重要了。只需要升级你的笔记本,然后从版本库中克隆出 vim 和 tmux 的配置文件,就可以再次回到配置最优的操作环境了。而且这一切只需要短短的几分钟。

总之,这些就是人们喜爱 tmux 的原因。当然即使你的生活不是四处奔波,也一样能体验到 tmux 带来的好处。

那么 screen 呢?

问得好。tmux 和 screen 很像,但比 screen 更好。要问好在哪里,简单的回答就是虽然与 screen 的功能相同,但是 tmux 设计得更好。screen 虽然可用,但是很不稳定。

以下是一些 tmux 超越 screen 的地方:

  • screen 的项目大体上已经终止了,并且代码中有大量的问题
  • tmux 是一个活跃的项目,并且其代码库经常进行更新
  • tmux 使用的是真正的客户端/服务器模型,而 screen 只是模拟了这种模型的行为
  • tmux 同时支持 emacs 和 vim 的快捷键
  • tmux 支持自动重命名窗口
  • tmux 可以高度的脚本化
  • tmux 的窗口分割功能更加先进

这些优点已经足够了吧,开始使用 tmux 吧。

基础

首先要告诉诸位的是 tmux 中的一个全局的快捷键开关,开关开启后就可以通过快捷键完成很多任务。

tmux 的快捷键

tmux 默认使用 Ctrl-b 作为激活快捷键的开关,开关开启后就可以通过快捷键迅速调用大量的功能。下面就给出一些基本功能的调用方法:

首先按下

$ Ctrl-b

接下来就可以按下一些后面将会讲解的快捷键了。不过先不要着急,可以先为能方便地使用组合键 Ctrl-b 做一点准备。不妨在操作系统中将键盘上的 CAPSLOCK 键映射为 Ctrl 键,这样当需要按下这个组合键时,小拇指的移动就可以更加舒服了。

运行 tmux

好了,下面让我们从运行 tmux 开始。首先选择一台你希望在断开会话后依然可以重新接入的计算机(对我来说这通常是远程服务器),然后在上面运行如下的命令:

$ tmux

很简单对吧。这样就开启了一个 tmux 的会话,你可以断开这个会话并在稍后再重新接入。

显示所有会话

由于 tmux 的理念是可以开启多个会话,并且可以自由地断开会话后重新接入,为此我们需要首先能看到可用的会话。有两种方法可以实现这个目的:

1
2
3
4
# Via shortcut (by default Ctrl-b)
# 使用快捷键(默认为 Ctrl-b)
$ Ctrl-b s
1
2
3
4
# Via tmux command
# 使用 tmux 的子命令
$ tmux ls

上面两种方法的效果相同,都可以得到类似下面的结果:

1
0: 1 windows (created Thu Nov 28 06:12:52 2013) [80x24] (attached)

新建会话

下面我们就来新建一个会话。可以使用 new 命令新建会话,并且该命令允许以参数的形式传递一个会话名。我的建议是在新建时要提供一个会话名以便于日后管理。

1
$ tmux new -s session-name
1
2
3
4
# Without naming the new session (not recommended)
# 新建会话但并不指定名字 (不推荐这样做)
$ tmux new

接入一个之前的会话

既然我们已经创建了多个带有名称的会话,那么就可以随时接入了,有几种方法可以实现接入会话:

可以简单地输入 tmux a 命令,这样可以接入第一个可用的会话:

1
$ tmux a

或者可以通过参数指定一个想接入的会话:

1
$ tmux a -t session-name

从会话中断开

可以使用 detach 命令断开已有的会话(因此才会有稍后重新接入会话这么一说)。

$ tmux detach

也可以使用快捷键断开会话:

$ Ctrl-b d

关闭会话

要关闭会话的话,可以使用如下的命令,该命令和接入会话时所使用的命令很像:

$ tmux kill-session -t session-name

提示:关闭窗口时也可以使用类似的命令,只不过要把 kill-session 换成 kill-window。另外,还可以使用 tmux killall 同时关闭 tmux。

配置

与其他工具一样,一旦配置好了 tmux,使用起来就将会非常顺手。下面就给出几个通常需要配置的项目:

  • tmux 的主要快捷键
  • 屏幕下方的状态条
  • 自定义的各种快捷键

我使用了一些相当简单的配置:

1
2
# Set a Ctrl-b shortcut for reloading your tmux config
#设置 Ctrl-b 快捷键,用于重新加载 tmux 的配置文件

access log,error log和system log。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
bind r source-file ~/.tmux.conf
# Rename your terminals
# 重命名终端
set -g set-titles on
set -g set-titles-string '#(whoami)::#h::#(curl ipecho.net/plain;echo)'
# Status bar customization
# 自定义状态条
set -g status-utf8 on
set -g status-bg black
set -g status-fg white
set -g status-interval 5
set -g status-left-length 90
set -g status-right-length 60
set -g status-left "#[fg=Green]#(whoami)#[fg=white]::#[fg=blue]
(hostname -s)#[fg=white]::##[fg=yellow]#(curl ipecho.net/plain;echo)"
set -g status-justify left
set -g status-right '#[fg=Cyan]#S #[fg=white]%a %d %b %R'

tmux 默认会先从 /etc/tmux.conf 加载系统级的配置项,然后从 ~/.tmux.conf 加载用户级的配置项。也可以使用参数 -f 指定一个配置文件。——译者注

这里有一点值得注意,我使用了 ipecho.net 而不是 icanhazip 来获取计算机当前的 IP 地址(IPv4)。虽然也有很多教程在使用 icanhazip,但是凭我的经验,ipecho.net 的速度更快,更稳定。

提示:如果你感兴趣,可以来这里查看我使用的最新配置。

高级功能

我平时常用的功能就是这些了。不过,我也会使用一些 tmux 中更强大的功能。

窗口和窗格

img

这些高级功能之一就是 tmux 可以将一个会话分割成若干个称为窗口(Window)和窗格(Pane)的相互分离的组件。这种逻辑上的分割使用户可以轻松安排各种各样的操作。

下面就来看一看这几个概念之间的关系。

层次结构

img

如上图所示,一个会话(Session)可以包含多个窗口,一个窗口(Window)可以包含多个窗格(Pane)。这就是我对这些概念的简单理解。当然如果诸位有更权威或者更实用的解释,我很乐意洗耳恭听。

  • 会话适用于分别管理大的工作内容,例如日常工作,实验或是系统管理,都可以分别在一个会话中进行。
  • 窗口适用于分别管理这些大工作中的项目。例如,在用于实验的会话中可能有一叫做 noderestapi 的窗口用于调试 node REST API,有一个叫做 lua 的窗口用于调试 lua 脚本。
  • 窗格适用于查看当前的项目。例如,在系统管理的会话中有一个叫做 logs 的窗口,在这个窗口中可以打开多个窗格分别用于查看 access log,error log和system log。

我们也可以在会话中直接创建窗格,而不需要先创建一个窗口。我有时也会这样做。当阅读完“层次结构”这一小节,希望我的这种做法没有听起来那样恐怖。正如我在一开始谈到的,我更倾向于简化 tmux 的使用。

在窗格间移动光标

虽然有默认的在窗格间移动光标的方法,但是我并不清楚是什么。因为我习惯用 vim,所以我会用hjkl 键在窗格间移动光标。为此,要加入如下的配置:

1
2
3
4
5
6
7
8
9
10
# Remap window(pane?) navigation to vim
# 用 vim 的方式在窗格间移动光标
unbind-key j
bind-key j select-pane -D
unbind-key k
bind-key k select-pane -U
unbind-key h
bind-key h select-pane -L
unbind-key l
bind-key l select-pane -R

建议

以下几条建议也许会有助于诸位的 tmux 之旅:

  1. 尽可能少打开会话和窗口。人类没有我们自认为的那样善于处理多任务。虽然打开 47 个窗格显得很强大,但是这并没有我们想象的那样实用。
  2. 当确实要使用窗口和窗格时,花一点时间为它们起个有意义的名字。这非常有用,如果只是用 0、1、2 这样的名字,切换会话或窗口时就会非常麻烦。
  3. 从基础的配置、操作开始使用 tmux,别一上来就把自己搞糊涂了。我曾遇到过很多人,他们花费了大量的时间配置 vim 或 tmux,而最终带来的结果却是不但把自己绕进去了,而且项目也没有进展。

    快捷键参考

按下 Ctrl-b 后的快捷键如下:

基础

  • ? 获取帮助信息

会话管理

  • s 列出所有会话
  • $ 重命名当前的会话
  • d 断开当前的会话

窗口管理

  • c 创建一个新窗口
  • , 重命名当前窗口
  • w 列出所有窗口
  • % 水平分割窗口
  • " 竖直分割窗口
  • n 选择下一个窗口
  • p 选择上一个窗口
  • 0~9 选择0~9对应的窗口

窗格管理

  • % 创建一个水平窗格
  • " 创建一个竖直窗格
  • h 将光标移入左侧的窗格*
  • j 将光标移入下方的窗格*
  • l 将光标移入右侧的窗格*
  • k 将光标移入上方的窗格*
  • q 显示窗格的编号
  • o 在窗格间切换
  • } 与下一个窗格交换位置
  • { 与上一个窗格交换位置
  • ! 在新窗口中显示当前窗格
  • x 关闭当前窗格> 要使用带“*”的快捷键需要提前配置,配置方法可以参考上文的“在窗格间移动光标”一节。——译者注

其他

  • t 在当前窗格显示时间