tmux学习笔记

Tmux 的快捷键前缀(Prefix)

为了使自身的快捷键和其他软件的快捷键互不干扰,Tmux 提供了一个快捷键前缀。当想要使用快捷键时,需要先按下快捷键前缀,然后再按下快捷键。Tmux 所使用的快捷键前缀默认是组合键 Ctrl-b(同时按下 Ctrl 键和 b 键)。例如,假如你想通过快捷键列出当前 Tmux 中的会话(对应的快捷键是 s),那么你只需要做以下几步:

  • 按下组合键 Ctrl-b (Tmux 快捷键前缀)
  • 放开组合键 Ctrl-b
  • 按下 s 键

Tmux 的配置文件

每当开启一个新的会话时,Tmux 都会先读取 ~/.tmux.conf 这个文件。该文件中存放的就是对 Tmux 的配置。

小提示:如果你希望新的配置项能够立即生效,那么你可以将下面这一行配置加入到文件~/.tmux.conf 中。

# bind a reload key

bind R source-file ~/.tmux.conf ; display-message "Config reloaded.."


这样配置了之后,每当向 ~/.tmux.conf 文件中添加了新的配置,只需要按下 Ctrl-b r 就可以重新加载配置并使新的配置生效,从而免去了开启一个新的会话。

Tmux 中最棒的功能

C-b c 创建一个新窗口

C-b & 关闭当前窗口

C-b p 切换到上一个窗口

C-b n 切换到下一个窗口

会话,窗口,面板

tmux有三个基本概念:会话,窗口和面板。当你输入tmux后,tmux实际做的事是首先创建一个会话,然后在这个会话中创建一个窗口,这个窗口只包含一个面板,你在其中看到的终端实际上都属于tmux的某个面板。

  • Ctrl-b %    创建一个竖直放置的窗格

  • Ctrl-b "    把屏幕沿水平方向分割

  • Ctrl-b o    跳到下个面板

  • Ctrl-b x    关闭当前面板

在 Tmux 的窗格间移动光标也很简单,只需要先按下 Tmux 的快捷键前缀,然后再按下对应的方向键就可以让光标进入到目标窗格了。

一个会话可以包含多个窗口,我们可以用会话来组织窗口,会话相当于一个工作环境,比如我们可以创建一个work的会话,里面放我们平时开发需要的窗口,tmux默认会创建一个会话,我们也可以通过参数创建指定名称的会话,例如

tmux new-session -s work

在控制台中输入这条命令就可以创建一个名为work的会话并进入它,我们也可以同时指定这个会话中第一个窗口的名字,比如mysql:

tmux new-session -s work -n mysql

在控制台上可以通过下列命令关闭会话work:

tmux kill-session -t work

关于会话有两个非常重要的操作,即attach和detach,attach就是让某个会话到前台来运行,而detach则是将某个会话放到后台。通常,当我们打开tmux时,tmux在创建一个会话的同时也会attach到这个会话,所以我们会立即看到tmux的窗口。在某个会话中,我们按C-b d会detach这个会话,也就会回到原先的终端控制台,但实际上并没有退出这个会话,比如你可以通过在终端中输入下列命令重新attach到work会话:

tmux attach -t work

一个时刻可能存在多个会话,在tmux外面通过下列命令可以列出当前有哪些会话:

tmux ls

在我们创建会话的同时也可以加上-d选项以表示不自动attach到这个新会话:

tmux new-session -s work -d

上面的一些以tmux打头的命令都是tmux提供的外部接口,是在命令行中供我们直接运行的,事实上,除了对会话的操作之外,在外部也可以直接创建窗口,例如:

tmux new-window -n project -t work

这条命令可以针对work会话创建一个名为project的窗口。

在创建会话和窗口时甚至可以指定要执行的命令:

tmux new-session -s work -n dev -d "ssh user@example.com"

有了tmux的各种强大的外部命令,我们就可以自定义脚本,自动化很多事情:

tmux new-session -s work -n mysql -d 'mysql'
tmux new-window -n editor -t work
tmux send-keys -t work:editor 'emacs' C-m

将上述命令写在一个shell脚本里,就可以一键完成下述功能:创建一个名为work的会话,第一个窗口命名为mysql,并在其中执行mysql命令进入mysql,第二个窗口名为editor,并在其中打开emacs。

按键同步发送

比如有两台机器,首先在一个窗口中开两个面板,分别连到这两台机器,然后按C-b :set synchronize-panes即可开/关面板的同步模式

永不断线

tmux实际上是server/client模式,当创建第一个会话时,server就会运行,以后的会话都以attach/detach的方式被server服务,当所有会话都退出时,server才会退出。在我们工作中,经常是SSH连接到服务器上去写代码,但由于网络的不稳定性,会偶尔发生SSH连接中断的情况,这样我们之前的会话就会丢失,如果是一个nohup的后台任务还好,只要我们重新连上去之后,还是可以找到的(但至少需要回到事发现场,比如重新cd到原来的文件夹等),而如果我们正在写代码,还没来得及保存,很可能就杯具了(除非某些编辑器刚好把你最新的代码自动保存过)。tmux不会存在这个问题,不信,你可以在终端中打开tmux,然后关闭这个终端,再打开一个新的终端,输入tmux ls看看,你会发现之前的会话仍然还在,你需要做的只是attach它就行!那么我们平常在SSH连接到服务器上后,再通过tmux去开启我们的工作会话,不管你在里面干什么,都不用担心断线,因为tmux server会帮你保存你的会话,你随时可以attach它,而且你的工作现场一直在那,连目录都不用切换,除非你真的kill掉它。

在文本间移动光标

在 Tmux 中可以使用与 Vim 极为相似的方式在文本间移动光标。正如你熟知的那样,用 k键可以将光标移动到上一行,用 w 键可以向后移动一个单词等等。而且还可以通过把 Tmux 设为 vi 模式,使其与 Vim 的操作更加接近。为此,需要将以下配置加入到文件 ~/.tmux.conf 中。

# Use vim keybindings in copy mode
setw -g mode-keys vi

将复制下来的文本发送到系统的剪贴板中

在默认情况下,当从 Tmux 中复制文本时,复制下来的文本只能粘贴到同一个 Tmux 会话中。若要使复制下来的文本可以粘贴到任何位置,就需要让 Tmux 将文本复制到系统的剪贴板。为此,我们需要这样做:

安装 retach-to-user-namespace。用 brew 安装的话将会非常简单,只需要运行下面这条命令:

$ brew install reattach-to-user-namespace

在配置文件 ~/.tmux.conf 中加入以下内容:

# invoke reattach-to-user-namespace every time a new window/pane opens
set-option -g default-command "reattach-to-user-namespace -l bash"

既然已经设置成了 vi 模式,也安装了 rettach-to-user-namespace,下面就让我们来看看如何从 Tmux 的会话中复制文本吧。假设要复制的是 IP 地址,于是我们先运行了 ifconfig命令。接下来就请跟随以下的步骤:

首先按下 Ctrl-b [ 进入复制模式,然后可以看到一小段高亮的文本出现在了屏幕的右上角,接下来就可以像在 Vim 中一样用 jkl 和 h 等键在文本间移动光标了。

把光标移动到想复制的文本上后再按下空格键就可以开始选择文本了(这和在 Vim 中复制文本的步骤一模一样)。

选择完要复制的文本后再按下回车键。

这样 IP 地址就复制下来并可以粘贴到任何地方了。

让复制文本的操作更像 Vim

你还可以设置 Tmux 使用 v 键选择文本,用 y 键复制文本。为此只需要将下面的配置项加入到配置文件 ~/.tmux.conf 中。

# start selecting text typing 'v' key (once you are in copy mode)
bind-key -t vi-copy v begin-selection
# copy selected text to the system's clipboard
bind-key -t vi-copy y copy-pipe "reattach-to-user-namespace pbcopy"

结对编程

结对编程是不是很酷?很简单,因为它的会话可以被多个client attach,比如A和B两人分别在家通过SSH连接到服务器上,然后都attach到同一个会话中,那么A和B的操作彼此都可以看到,简直碉堡了!

调整 Tmux 以增强其同 Vim 的集成度

调整背景的配色方案

当我第一次通过 Tmux 打开 Vim 时,我发现 Vim 的颜色没有正确显示。正如下图所示,只有有字符的地方才有背景色。

这个问题是因为通过 Tmux 运行 Vim 需要配置一个特殊的终端参数(term parameter)。请将下面这行配置添加以你的 ~/.vim 文件中。

if exists('$TMUX')
  set term=screen-256color
endif

在更新了配置文件 ~/.vimrc 以后,颜色应该就可以正确显示了。

调整光标的形状

在默认情况下,当通过 Tmux 运行 Vim 时,无论当前 Vim 是处于插入模式、可视模式还是其他模式,光标的形状都是一样的。这样就很难判断当前的 Vim 模式是什么。若要避免这个问题,就需要让 Tmux 通知 iTerm 更新光标的形状。为此,需要将以下配置加入到文件 ~/.vimrc 中。

if exists('$ITERM_PROFILE')
  if exists('$TMUX') 
    let &amp;t_SI = "<Esc>[3 q"
    let &amp;t_EI = "<Esc>[0 q"
  else
    let &amp;t_SI = "<Esc>]50;CursorShape=1x7"
    let &amp;t_EI = "<Esc>]50;CursorShape=0x7"
  endif
end

调整粘贴时的文本缩进

在 Vim 中粘贴文本时可能会遇到这样的问题,有时文本的缩进会发生变化,特别是在粘贴大量的文本时,这个问题会更加明显。虽然可以通过在粘贴前执行 :set nopaste 来解决这个问题,但是这里还有一种更好的解决方法。就是把下面这段配置加入到配置文件 ~/.vimrc中,这样 Vim 就会自动地阻止粘贴文本时的自动缩进。

" for tmux to automatically set paste and nopaste mode at the time pasting (as
" happens in VIM UI)
 
function! WrapForTmux(s)
  if !exists('$TMUX')
    return a:s
  endif
 
  let tmux_start = "<Esc>Ptmux;"
  let tmux_end = "<Esc>"
 
  return tmux_start . substitute(a:s, "<Esc>", "<Esc><Esc>", 'g') . tmux_end
endfunction
 
let &amp;t_SI .= WrapForTmux("<Esc>[?2004h")
let &amp;t_EI .= WrapForTmux("<Esc>[?2004l")
 
function! XTermPasteBegin()
  set pastetoggle=<Esc>[201~
  set paste
  return ""
endfunction
 
inoremap <special> <expr> <Esc>[200~ XTermPasteBegin()

其他能够提升 Tmux 体验的工具或技巧

Tmuxinator (为项目自动创建会话)

假设你正在开发应用程序 A。在开发过程中,经常要创建 Tmux 会话,会话中包含“server”、“editor”(用于编写代码)和“shell”(用于运行系统命令)这 3 个窗口。不仅如此,在一天之中的某个特定的时间你还需要临时进入到应用程序 B 的开发工作中。于是你又不得不创建另一个会话,虽然有略微的不同(比如目录和某些命令),但是会话中还是要包含应用程序 A 中的那 3 个窗口。但是有了 Tmuxinator,你就可以为每个Tmux 会话声明一个配置,然后用 1 条命令就能创建出这个会话了。这功能太棒了,不是吗。

Tmuxinator 是一个 Ruby 的 gem 包,可用于创建 Tmux 的会话。它的工作方式是先在配置文件中定义会话中的细节,然后用 1 条命令创建出这些会话。下面就让我们看看如何安装 Tmuxinator 以及如何添加配置来为指定项目开启一个会话。可以通过运行如下命令安装 Tmuxinator 的 gem 包。

$ gem install tmuxinator

安装好了 Tmuxinator 以后,就可以在系统 Shell 中运行 tmuxinator 或 mux 命令了。下面就让我们为上述的应用程序(有 3 个窗口,分别是“servers”, “editor” 和 “shell”)来创建一个配置文件吧。下面这条命令的作用是为这个项目创建并打开一个配置文件。

$ tmuxinator new project_a

按下回车键后,就会自动打开文件 ~/.tmuxinator/project_a.yml。为了实现项目 A 所需的配置,你需要把 project_a.yml 的内容更新为:

name: project_a
root: <the-folder-of-project-A>
 
windows:
  - server: <command-to-start-application-server>
 
  - editor:
    layout: even-horizontal
    panes:
      - vim
      - <command-to-launch-tests-guard>
 
  - shell: ''

一旦将上面的配置添加到了项目 A 的 Yaml 文件中,只需要运行下面这条命令就可以启动 Tmux 的会话了。

$ tmuxinator start project_a

当然如果愿意的话,你也可以使用 Tmuxinator 命令的别名:

$ mux start project_a

大功告成了。现在,每当想进入项目 A 的编码工作时,就只需要运行 Tmuxinator 命令。

可以到这里查看Tmuxinator的官方文档。

美化 Tmux 的状态栏

默认情况下,Tmux的状态栏看起来是下图这个样子(图中绿底部分):

我们可以根据需要改变状态栏的外观。对我来说,我喜欢下图这种清爽的外观。

为了达到上图的效果,我将如下的配置加入到了配置文件 ~/.tmux.conf 中。

# 状态栏
  
# 颜色
  set -g status-bg black
  set -g status-fg white
 
  
# 对齐方式
  set-option -g status-justify centre
 
  
# 左下角
  set-option -g status-left '#[bg=black,fg=green][#[fg=cyan]#S#[fg=green]]'
  set-option -g status-left-length 20
 
  
# 窗口列表
  setw -g automatic-rename on
  set-window-option -g window-status-format '#[dim]#I:#[default]#W#[fg=grey,dim]'
  set-window-option -g window-status-current-format '#[fg=cyan,bold]#I#[fg=blue]:#[fg=cyan]#W#[fg=dim]'
 
  
# 右下角
  set -g status-right '#[fg=green][#[fg=cyan]%Y-%m-%d#[fg=green]]'

参考:http://blog.jobbole.com/87584/  http://abyssly.com/2013/11/04/tmux_intro/