cover

今天决定学一下 Tmux 怎么用,因为经常发现要开几个 Terminal Tabs 处理不同的东西,然后要对照的时候来回切真的很累。手按快捷键累,眼睛盯着来回在跳动的文本也累。Vim 本身其实也很容易可以左右上下的切分视图,但是切出来的都是 Vim。虽然想要运行 Shell 命令也不是不可以,但是终究没有 Tmux 直接切分终端来得方便。

当然 Tmux 好处还有很多,比如 ssh 连接到服务器打开 session,detach 到后台,断开 ssh 之后再连上去 atach 回之前的 sesion 东西都在。但基本上我看上的就是切割 pane 这个了,也懒得说其他了,用得上再去学。

1. What is TMUX

由于我用的 Debian sid,所以安装肯定是没什么说的:

1
sudo apt install tmux

This APT has Super Cow Powers.

首先 Tmux 到底是什么呢?Yet another terminal?我们 man tmux 看看 :

tmux — terminal multiplexer

哦,名字原来这么来的。但是这个 multiplexer 是个什么东西?这单词我都不认识。谷歌翻译告诉我,复用器的意思。所以,tmux 的中文名就是终端复用器。那复用器又是个什么东西 ….. 不知道。算了,往下看吧:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
DESCRIPTION
     tmux is a terminal multiplexer: it enables a number of terminals to be created, 
     accessed, and controlled from a single screen.  tmux may be detached from a 
     screen and continue running in the background, then later reattached.

     When tmux is started it creates a new session with a single window and displays it
     on screen.  A status line at the bottom of the screen shows information on the 
     current session and is used to enter interactive commands.

     A session is a single collection of pseudo terminals under the management of tmux.
     Each session has one or more windows linked to it.  A window occupies the entire 
     screen and may be split into rectangular panes, each of which is a separate pseudo 
     terminal (the pty(4) manual page documents the technical details of pseudo terminals).
     Any number of tmux instances may connect to the same session, and any number of windows
     may be present in the same session.  Once all sessions are killed, tmux exits.

     Each session is persistent and will survive accidental disconnection (such as ssh(1) 
     connection timeout) or intentional detaching (with the ‘C-b d’ key strokes).
     tmux may be reattached using:

           $ tmux attach

     In tmux, a session is displayed on screen by a client and all sessions are managed by a 
     single server.  The server and each client are separate processes which communicate 
     through a socket in /tmp.

我就一边看一边随便翻译一下,中间夹杂我的个人想法。可能有错误。

tmux 是个终端复用器,终端复用器是什么呢?它允许在一个屏幕(screen)里创建、使用和控制多个终端。这个屏其实按我们就是一个 terminal 窗口了。

看到这里我就稍稍懂了一点了。因为和早期计算机(感觉这里叫计算机比叫电脑合适)其实只有通过终端连接进行操作,而这个终端其实就是个连上去的显示器 + 键盘之类的外设,然后连上去一登录就是个 tty 这样的。可以看到 tty 就是直接只有一屏,不存在窗口的概念,所以就说屏幕(screen)。其实这样翻译不是很准确,屏幕给人的感觉是屏幕这个实体的东西,但是这里应该指显示的一屏内容。这时候我们用来连计算机这个终端是物理的实体存在的东西。但因为我们现在大都是图形化的一个窗口来模拟这个终端,所以现在我们用的 terminal 的都叫做 Terminal Emulator 这就很好理解了,我们的这个软件窗口就是模拟当初连计算机的那个实体终端的。tmux 就是把一个终端复用,相当于一个变成了多个了。所以 tmux 的 screen 对应到我们 terminal 里使用时其实我们的 terminal emulator 的一整个窗口。tmux 下面出现的 server - client 概念其实也从这儿来,我们终端连计算机就是服务器-客户端(终端)这样的模型。

tmux 能从当前屏 detach 掉,但是它还会在后台运行,并且可以随时 atach 回去。tmux 启动时会在屏幕上创建并显示在一个只有一个 window 的新 session。屏幕底部会显示一个状态栏。状态栏就展示了当前 session 的一些信息,并可以用来输入交互式的命令。

session 是 tmux 管理的多个伪终端的集合。每个 session 下可以有一个或者多个 window,而每个 window 都会直接占据当前屏幕全部并且可以进一步分割成多个矩形 pane。每个 pane 里都都一个伪终端。任意个 tmux 可以连接到一个 session,一个 session 里可以有任意个 window。所有 session 都关掉的时候 tmux 会退出。

每个 session 都是可以保持的,所以意外的 ssh 连接断掉或者按到 detach 的快捷键时都可以再 attach 回去。

tmux 由 client 展示在屏幕上,而多个 session 都由同一个 server 管理。server 和每个 client 之间的连接都是单独的进程,并可以通过 /tmp 下的一个 socket 来互相沟通。

2. First look

嗯,终于看完了。大概对 tmux 也有个了解了。层级关系:

服务器 (server) + 客户端 (client) –> 会话 (session) –> 窗口 (window) –> 窗格 (pane)

所以基本上我们打开一个 terminal 进入 tmux 的同时就生成了一个 server-client 连接 session。这个 session 会直接占据当前 terminal 整个显示空间。然后一个 session 下面可以有多个 window,就相当于我们在 terminal 里开了几个标签。一个 window 还能切分成 pane,这就是我想用的切分终端窗口的功能了。关系捋清楚了,再看我们的封面图:

cover

这是一个 session 打开了之后的样子,下面状态栏显示这个 session 名字叫做 MySn,里面有 0 -10 一共 11 个 window 并且每个 window 都有对应的名字(编号从 0 开始。然后我也不知道为啥我啥也没配置打开默认就这么多 window 了 …)。当前在第一个(编号 0)叫做 zsh 的 window 里,下划线和星号就是表示的当前所在 window 了。然后当前这个 window 被分成了 3 个 pane,左上的 vim 打开了 tmux 的配置文件 ~/.tmux.conf,左下运行的 screenfetch,右边大 pane 打开了 man tmux。嗯,概念基本清晰了,开始配置了。

3. 配置 tmux

搞清楚概念了我们就要开始配置然后弄得自己顺手了。

首先得知道 tmux 和 vim 有点像,一切操作靠键盘快捷键。类似于快捷键前面按前缀 Ctrl、Alt、Super 一样,tmux 内部快捷键也有一个 prefix,默认是 Ctrl + b。但是我手小,这个键位有挑战性,所以按照网上很多人一样第一时间改掉这个,我改为了 Ctrl + x。所以下面快捷键都会以 Ctrl + x 开头,但是我写做 。(其实开始是用 Ctrl + a,这也是网上我看别人用得最多的。但是用了发现也 Shell 本身 Ctrl + a 到命令行首冲突,所以又改为 Ctrl + x)

一旦进入 tmux 由于几乎全是快捷键操作,会有一点第一次接触 vim 一样的手足无措感。所以得之后进入退出和管理当前的 session:

3.1 tmux 进入退出

终端 tmux 就能直接进去了。其他:

  • tmux new -s:建立新 session (-s 其实就是 session 咯),-s 选项后面写 session-name
  • <prefix> d: 退出会话,回到 Shell 的终端环境。这个和 Shell 类似,Ctrl + d 退出。但是这里其实是 detach 的意思

这下平安了。知道怎么怎么进怎么出。稍微安心点。继续:

  • tmux ls :查看当前后台 session。同时也会列出 session 名和里面有多少 window
  • tmux a -t Sn 进入后台的名为 Sn 的会话,a 是 attach (写 attach 也可以),t 是 target session
  • tmux rename -t OldName NewName:重命名 session。<prefix> $ 一样进入重命名 session 状态,<prefix> , 则重命名当前的 window

  • <prefix> s:S 应该是 status,显示当前 session 的信息。会详细现实所有 window 及其 pane 的信息,而且可以方向键选择切换

  • tmux kill-session -t Sn:结束名为 Sn 的 session。

  • <prefix> ::进入命令模式(状态栏颜色会变)。此时输入 kill-session -t Sn 一样可以结束 Sn 这个 session,直接 kill-session 结束当前这个 session,此时终端 tmux ls 再看后台的这个 session 就没了。

3.2 其他快捷键和配置

全局快捷键

知道怎么进入退出和简单管理 sesion 之后,现在我们可以开始用了。然后就是了解快捷键和配置快捷键了。上面已经说过我们改了默认的前缀 Ctrl + bCtrl + x。在 ~/.tmux.conf 配置文件里就是:

1
2
3
4
# Change the prefix key to C-a
unbind C-b
set -g prefix C-x
bind C-x send-prefix

然后由于开始一直在改配置文件,想直接生效而不用一直退出重新打开,我们定义一个 prefix + r 来重加载配置文件:

1
2
# <prefix>-r ro reload config
bind r source-file ~/.tmux.conf \; display-message "Config reloaded"

然后按照网上的推荐,把切换 pane 的快捷键改成了 vim style:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# vim style switching panes
#up
bind-key k select-pane -U
#down
bind-key j select-pane -D
#left
bind-key h select-pane -L
#right
bind-key l select-pane -R
# 以及大写用来调节大小
bind L resize-pane -L 10    # 向左扩展
bind R resize-pane -R 10    # 向右扩展
bind K resize-pane -U 5     # 向上扩展
bind J resize-pane -D 5     # 向下扩展

但是我还嫌麻烦,最后 Google 了终于找到了鼠标选定 pane 和调节 pane 大小的选项了:

1
2
3
4
# Turn the mouse on, but without copy mode dragging
set -g mouse on
unbind -n MouseDrag1Pane
unbind -Tcopy-mode MouseDrag1Pane

这下就爽了,鼠标选 pane 和 window 以及调节 pane 大小,少记好几个快捷键。

我还把默认配置文件一打开配置好的 11 个 window 那些行直接删掉了。所以现在我杀掉所有 session 重新建一个进去的话就只有默认 session,只有一个窗口。我们先 <prefix> $ 给 session 取个名字,然后 <prefix> , 给这个 window 取名字。

现在只有一个 window,想新开一个呢?新开了一个我想要切回去呢?一大波快捷键来了:

window

  • <prefix> c 就会创建一个新的 window,c 大概是 create 吧
  • <prefix> p:切换到上一个 window,p 就是 previous
  • <prefix> n: next,下一个 window
  • <prefix> 0: 切换到 0 号 window,依次类推可切到任意窗口
  • <prefix> w :window,会列出当前 session 所有 window,通过上、下键切换窗口
  • <prefix> &: 关闭当前 window,会有确认提示

pane

好了,终于到了怎么使用 pane 了:

  • <prefix> %:创建垂直切割的 pane (水平线形成左右 pane)
  • <prefix> ":创建水平分割的 pane (水平线形成上下 pane)
  • <prefix> o:在 pane 之间循环切换。当前活动 pane 四周切割线为绿色
  • <prefix> ArrowKey:方向键切 pane。当然上面也定义了 vim style 的切换键
  • <prefix> z:zoom,最大化当前 pane,再按一次 <prefix> z 恢复原样
  • <prefix> t:在 pane 里显示一个数字时钟,t 就是 time 咯
  • <prefix> q:会显示当前 window 所有 pane 的编号,在编号消失之前(要眼疾手快!)按数字就能切过去了。q 大概是 query 吧
  • <prefix> x:关闭当前 pane,会有确认提示

4. 我的自定义配置

前面说了很多我改的选项,其实有一个最不爽的我没说。默认 <prefix> %/” 切分 pane 这个我是真的无力吐槽。感觉一点道理没有记不住不说,% 还得按 Shift,累死人。所以我按照形象记忆,把键盘的 |- 设置为切分。由于 | 需要 Shift + \,所以最终直接绑 \,反正键盘上能看到就 OK。

以及其他一些选项不细说,贴上我的配置文件吧:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#################################
##########    Options    ########
#################################

# Turn the mouse on, but without copy mode dragging
# this also enable mouse to choose or resize a pane,  as well as to choose window
set -g mouse on
unbind -n MouseDrag1Pane
unbind -Tcopy-mode MouseDrag1Pane
# tweak status line
set -g status-right "%H:%M"
set -g window-status-current-attr "underscore"
# 提示信息的持续时间;设置足够的时间以避免看不清提示,单位为毫秒
set-option -g display-time 5000
# 控制台激活后的持续时间;设置合适的时间以避免每次操作都要先激活控制台
set-option -g repeat-time 1000
set-window-option -g display-panes-time 1500
# enable utf-8
set -gq status-utf8 on
# use 256 colors
set-option -g default-terminal "screen-256color"
# Enable RGB colour if running in xterm(1)
set-option -sa terminal-overrides ",xterm*:Tc"
# Change the default $TERM to tmux-256color
set -g default-terminal "tmux-256color"
# scrollback buffer n lines
set-option -g history-limit 100000                 
# 窗口的初始序号默认为 0 开始,这里设置为 1
set-option -g base-index 1
# pane 一样设置为 1 开始
set-window-option -g pane-base-index 1
# No bells at all
set -g bell-action none
# Keep windows around after exit?
set -g remain-on-exit off

# If running inside tmux ($TMUX is set), then change the status line to red
%if #{TMUX}
set -g status-bg red
%endif

##############################################
############ keyboard shortcuts ##############
##############################################

# Change the prefix key to C-a
set -g prefix C-x
unbind C-b
bind C-x send-prefix

# <prefix>-r ro reload config
bind r source-file ~/.tmux.conf \; display-message "Config reloaded"

# vim style switching panes
#up
bind-key k select-pane -U
#down
bind-key j select-pane -D
#left
bind-key h select-pane -L
#right
bind-key l select-pane -R
# 向左扩展
bind L resize-pane -L 10
# 向右扩展
bind R resize-pane -R 10
# 向上扩展
bind K resize-pane -U 5
 # 向下扩展
bind J resize-pane -D 5

# select last window with <prefix> + C-l
bind-key C-l select-window -l

# [prefix |] / [prefix -] to split panes
unbind '"'
unbind %
bind-key \ split-window -h
bind-key - split-window -v

# ESC to start vim style copy and paste
bind Escape copy-mode
bind-key -Tcopy-mode-vi 'v' send -X begin-selection
bind-key -Tcopy-mode-vi 'y' send -X copy-selection
unbind p
bind p pasteb
setw -g mode-keys vi      # Vi 风格选择文本

好了,暂时这样用。用一阵子快捷键肯定会调整的。到时候就不再更新这里了,反正最后都传到我的 Linux-config-bak 这个 Github repo 备份了。

参考: